{"id":15692761,"url":"https://github.com/genaker/magento_gridjs","last_synced_at":"2025-05-07T14:47:32.170Z","repository":{"id":225069966,"uuid":"764981180","full_name":"Genaker/magento_gridjs","owner":"Genaker","description":"GridJS integration with Magento 2. DataTable, Grid JS, AG Grid","archived":false,"fork":false,"pushed_at":"2025-04-29T05:32:40.000Z","size":301,"stargazers_count":20,"open_issues_count":0,"forks_count":4,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-04-29T06:27:25.067Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Genaker.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-02-29T03:57:57.000Z","updated_at":"2025-04-29T05:32:43.000Z","dependencies_parsed_at":"2024-03-05T00:30:45.424Z","dependency_job_id":"0a5050d9-2d64-49ad-84ae-4cc41d773b72","html_url":"https://github.com/Genaker/magento_gridjs","commit_stats":null,"previous_names":["genaker/magento_gridjs"],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Genaker%2Fmagento_gridjs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Genaker%2Fmagento_gridjs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Genaker%2Fmagento_gridjs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Genaker%2Fmagento_gridjs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Genaker","download_url":"https://codeload.github.com/Genaker/magento_gridjs/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252898958,"owners_count":21821710,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-03T18:39:57.165Z","updated_at":"2025-05-07T14:47:32.154Z","avatar_url":"https://github.com/Genaker.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Mage Grid Module\n\nA powerful and flexible grid system for Magento 2 that provides an easy way to create and manage data grids in the admin panel.\n\n## Features\n\n- **Flexible Data Sources**: Support for both collection-based and SQL-based data sources\n- **AJAX Support**: Built-in AJAX functionality for smooth data loading\n- **Customizable Fields**: Easy field configuration and management\n- **Built-in Filtering**: Advanced filtering capabilities\n- **Pagination**: Automatic pagination handling\n- **Frontend \u0026 Backend Support**: Works in both frontend and backend contexts\n- **Responsive Design**: Mobile-friendly grid layout\n- **Customizable Templates**: Easy to override and customize templates\n\n## Why Our Grid is Better Than Magento's Legacy Grid\n\nOur grid implementation offers several advantages over Magento's legacy grid system:\n\n1. **Modern Technology Stack**:\n   - Uses GridJS, a modern JavaScript grid library\n   - Built with Preact for efficient rendering\n   - Supports modern JavaScript features and async/await\n\n2. **Better Performance**:\n   - Lighter weight than Magento's legacy grid\n   - Faster rendering and data loading\n   - Reduced server load with client-side processing\n\n3. **Enhanced Flexibility**:\n   - Easy to customize columns and cells\n   - Support for both collection and SQL-based data sources\n   - Simple integration with Magento's UI components\n\n4. **Improved Developer Experience**:\n   - Cleaner code structure\n   - Better separation of concerns\n   - Easier to extend and maintain\n\n5. **Better User Experience**:\n   - Smoother interactions\n   - More responsive interface\n   - Better mobile support\n\n6. **Advanced Features**:\n   - Built-in AJAX support\n   - Advanced filtering capabilities\n   - Custom cell renderers\n   - Dynamic data loading\n\n7. **Integration with Magento**:\n   - Seamless integration with Magento's admin panel\n   - Support for Magento's UI components\n   - Compatible with Magento's theming system\n\n## Why This Grid is AI-First\n\nMage Grid is designed from the ground up to be **AI-first**. This means:\n\n- The codebase is structured for easy understanding and modification by AI coding assistants (like Cursor, GitHub Copilot, or ChatGPT).\n- Naming conventions, modularity, and documentation are optimized for AI-driven code generation and extension.\n- The grid is built to be easily extensible and customizable with minimal manual intervention, making it ideal for rapid prototyping and iterative development with AI tools.\n- Simple strait forward architecture and access to code with examples and documenttion makes it straightforward for LLMs to read, understand, and even improve your components. AI-Ready: Open code for LLMs to read, understand, and improve.\n\nThe design of the Mage Grids makes it easy for AI tools to work with your code. Its open code and simple API allow AI models to read, understand, and generate new components.\n\n### What Makes It AI-First?\n- **Consistent, clear naming**: Classes, methods, and templates are named for discoverability and semantic search.\n- **Separation of concerns**: Logic, templates, and configuration are cleanly separated, so AI can suggest or generate changes in isolation.\n- **Extensive inline documentation**: Comments and docblocks are written to help both humans and AI understand intent and usage.\n- **Configurable via XML and DI**: Most features (fields, processors, templates) are configured in XML or DI, so AI can suggest changes without deep PHP edits.\n- **Composable processors**: The data processor system is designed for easy extension and chaining, which is ideal for AI-driven code generation.\n- **Template-driven UI**: UI and JS are in templates, so AI can generate or modify UI logic without touching backend code.\n\n## How to Extend Mage Grid Using Cursor or AI\n\nYou can use AI tools like Cursor to:\n- Add new data processors (e.g., for custom formatting, badges, or links)\n- Add or modify grid fields and templates\n- Inject new JS/HTML for popups, modals, or custom actions\n- Refactor or optimize code for performance or maintainability\n\n### Example: Adding a Custom Data Processor with Cursor\n1. **Describe your goal in Cursor:**\n   - \"Add a processor that renders the 'priority' field as a colored badge.\"\n2. **Let Cursor search for DataProcessorInterface and StatusProcessor.**\n3. **Cursor generates a new PriorityProcessor.php:**\n   - Implements the interface, adds color logic, and registers in di.xml.\n4. **Update your layout XML to map the 'priority' field to the new processor.**\n\n### Example: Adding a Popup with AI\n1. **Describe your goal:**\n   - \"Add a popup that shows full row details when the 'Order Number' cell is clicked.\"\n2. **AI suggests a new JS function and a template snippet.**\n3. **Add the JS to an additional-html.phtml template and configure it in layout XML.**\n4. **AI updates the grid template to include the new popup logic.**\n\n### Practical Steps for AI-Driven Extension\n- Use Cursor's semantic search to find relevant classes, templates, or config files.\n- Use inline comments and docblocks to guide AI suggestions.\n- Use the modular template and processor system to add or override features without deep code changes.\n- Test changes iteratively, letting AI suggest fixes or improvements.\n\n**Tip:**\n- The more you describe your intent (in comments, commit messages, or AI prompts), the better the AI can help you extend or refactor the grid.\n\n### AI Assistant Integration\n\nThe Mage Grid module includes an advanced AI Assistant that helps users interact with the grid using natural language queries. The AI Assistant:\n\n- **Natural Language Filtering**: Users can type queries in natural language (e.g., \"show orders from last week\", \"find orders with status pending\") and the AI will convert them into appropriate filters.\n- **Terminal-like Interface**: When users type \"select\" or similar SQL-like keywords, the input field transforms into a terminal-like interface with green text on black background and a blinking cursor.\n- **Smart Suggestions**: Provides alternative filter suggestions when the query is ambiguous or when multiple filtering options are available.\n- **Context-Aware**: Takes into account current filters, pagination, and sorting when suggesting new filters.\n- **Error Handling**: Gracefully handles unclear queries and asks for clarification when needed.\n- **Performance Optimized**: Caches frequent queries and optimizes filter combinations for better performance.\n\n\n## Installation\n\n1. Copy the module to your Magento installation:\n```bash\ncp -r app/code/Mage/Grid /path/to/magento/app/code/\n```\n\n2. Enable the module:\n```bash\nbin/magento module:enable Mage_Grid\n```\n\n3. Run setup upgrade:\n```bash\nbin/magento setup:upgrade\n```\n\n4. Clear cache:\n```bash\nbin/magento cache:clean\n```\n\n## Usage\n\n### Basic Grid Setup\n\n1. Create a layout file (e.g., `view/adminhtml/layout/your_module_grid_index.xml`):\n```xml\n\u003c?xml version=\"1.0\"?\u003e\n\u003cpage xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"urn:magento:framework:View/Layout/etc/page_configuration.xsd\"\u003e\n    \u003cbody\u003e\n        \u003creferenceContainer name=\"content\"\u003e\n            \u003cblock class=\"Mage\\Grid\\Block\\MageGridBlock\" name=\"your_grid\"\u003e\n                \u003carguments\u003e\n                    \u003cargument name=\"viewModel\" xsi:type=\"object\"\u003eMage\\Grid\\ViewModel\\GenericViewModelGrid\u003c/argument\u003e\n                    \u003cargument name=\"collectionClass\" xsi:type=\"string\"\u003eYour\\Module\\Model\\ResourceModel\\YourCollection\u003c/argument\u003e\n                    \u003cargument name=\"fields\" xsi:type=\"array\"\u003e\n                        \u003citem name=\"id\" xsi:type=\"string\"\u003eID\u003c/item\u003e\n                        \u003citem name=\"name\" xsi:type=\"string\"\u003eName\u003c/item\u003e\n                        \u003citem name=\"created_at\" xsi:type=\"string\"\u003eCreated At\u003c/item\u003e\n                    \u003c/argument\u003e\n                \u003c/arguments\u003e\n            \u003c/block\u003e\n        \u003c/referenceContainer\u003e\n    \u003c/body\u003e\n\u003c/page\u003e\n```\n\n2. Create a controller (e.g., `Controller/Adminhtml/YourGrid/Index.php`):\n```php\n\u003c?php\nnamespace Your\\Module\\Controller\\Adminhtml\\YourGrid;\n\nuse Magento\\Backend\\App\\Action;\nuse Magento\\Framework\\View\\Result\\PageFactory;\n\nclass Index extends Action\n{\n    protected $resultPageFactory;\n\n    public function __construct(\n        Action\\Context $context,\n        PageFactory $resultPageFactory\n    ) {\n        parent::__construct($context);\n        $this-\u003eresultPageFactory = $resultPageFactory;\n    }\n\n    protected function _isAllowed()\n    {\n        return $this-\u003e_authorization-\u003eisAllowed('Your_Module::your_grid');\n    }\n\n    public function execute()\n    {\n        $resultPage = $this-\u003eresultPageFactory-\u003ecreate();\n        $resultPage-\u003esetActiveMenu('Your_Module::your_grid');\n        $resultPage-\u003egetConfig()-\u003egetTitle()-\u003eprepend(__('Your Grid Title'));\n        return $resultPage;\n    }\n}\n```\n\n### Custom Column Cells with Preact\n\nThe module uses GridJS with Preact for rendering custom column cells. Here's how to create custom column cells:\n\n1. **Basic Custom Column**:\n```javascript\nrequire(['jquery', 'gridjs'], function($, grid) {\n    jQuery(\"#yourGrid\").Grid({\n        columns: [\n            'Name',\n            'Email',\n            {\n                name: 'Actions',\n                formatter: (_, row) =\u003e html`\u003cbutton onclick=\"editItem(${row.cells[0].data})\"\u003eEdit\u003c/button\u003e`\n            }\n        ],\n        data: [\n            ['John Doe', 'john@example.com'],\n            ['Jane Smith', 'jane@example.com']\n        ]\n    });\n});\n```\n\n2. **Complex Custom Column with Magento Integration**:\n```javascript\nrequire(['jquery', 'gridjs'], function($, grid) {\n    jQuery(\"#yourGrid\").Grid({\n        columns: [\n            'Order ID',\n            'Customer',\n            {\n                name: 'Status',\n                formatter: (cell, row) =\u003e {\n                    const status = cell;\n                    const color = status === 'Complete' ? 'green' : 'red';\n                    return html`\u003cspan style=\"color: ${color}\"\u003e${status}\u003c/span\u003e`;\n                }\n            },\n            {\n                name: 'Actions',\n                formatter: (_, row) =\u003e {\n                    const orderId = row.cells[0].data;\n                    return html`\n                        \u003cdiv class=\"actions\"\u003e\n                            \u003cbutton onclick=\"viewOrder('${orderId}')\"\u003eView\u003c/button\u003e\n                            \u003cbutton onclick=\"editOrder('${orderId}')\"\u003eEdit\u003c/button\u003e\n                            \u003cbutton onclick=\"deleteOrder('${orderId}')\"\u003eDelete\u003c/button\u003e\n                        \u003c/div\u003e\n                    `;\n                }\n            }\n        ],\n        data: [\n            ['10001', 'John Doe', 'Complete'],\n            ['10002', 'Jane Smith', 'Pending']\n        ]\n    });\n});\n```\n\n3. **Custom Column with AJAX Data**:\n```javascript\nrequire(['jquery', 'gridjs'], function($, grid) {\n    jQuery(\"#yourGrid\").Grid({\n        columns: [\n            'Order ID',\n            {\n                name: 'Customer Details',\n                formatter: async (_, row) =\u003e {\n                    const orderId = row.cells[0].data;\n                    const response = await fetch(`/rest/V1/orders/${orderId}`);\n                    const data = await response.json();\n                    return html`\n                        \u003cdiv class=\"customer-details\"\u003e\n                            \u003cstrong\u003e${data.customer_firstname} ${data.customer_lastname}\u003c/strong\u003e\n                            \u003cbr/\u003e\n                            \u003csmall\u003e${data.customer_email}\u003c/small\u003e\n                        \u003c/div\u003e\n                    `;\n                }\n            }\n        ],\n        data: [\n            ['10001'],\n            ['10002']\n        ]\n    });\n});\n```\n\n4. **Custom Column with Magento UI Components**:\n```javascript\nrequire(['jquery', 'gridjs', 'Magento_Ui/js/modal/alert'], function($, grid, alert) {\n    jQuery(\"#yourGrid\").Grid({\n        columns: [\n            'Order ID',\n            {\n                name: 'Actions',\n                formatter: (_, row) =\u003e {\n                    const orderId = row.cells[0].data;\n                    return html`\n                        \u003cdiv class=\"actions\"\u003e\n                            \u003cbutton onclick=\"showOrderDetails('${orderId}')\"\u003eDetails\u003c/button\u003e\n                        \u003c/div\u003e\n                    `;\n                }\n            }\n        ],\n        data: [\n            ['10001'],\n            ['10002']\n        ]\n    });\n\n    window.showOrderDetails = function(orderId) {\n        alert({\n            title: 'Order Details',\n            content: `Loading order ${orderId}...`,\n            actions: {\n                always: function() {\n                    // Load order details via AJAX\n                }\n            }\n        });\n    };\n});\n```\n\n5. **Custom Column with Magento Form Elements**:\n```javascript\nrequire(['jquery', 'gridjs'], function($, grid) {\n    jQuery(\"#yourGrid\").Grid({\n        columns: [\n            'Order ID',\n            {\n                name: 'Status',\n                formatter: (cell, row) =\u003e {\n                    const orderId = row.cells[0].data;\n                    return html`\n                        \u003cselect onchange=\"updateStatus('${orderId}', this.value)\"\u003e\n                            \u003coption value=\"pending\" ${cell === 'pending' ? 'selected' : ''}\u003ePending\u003c/option\u003e\n                            \u003coption value=\"processing\" ${cell === 'processing' ? 'selected' : ''}\u003eProcessing\u003c/option\u003e\n                            \u003coption value=\"complete\" ${cell === 'complete' ? 'selected' : ''}\u003eComplete\u003c/option\u003e\n                        \u003c/select\u003e\n                    `;\n                }\n            }\n        ],\n        data: [\n            ['10001', 'pending'],\n            ['10002', 'processing']\n        ]\n    });\n});\n```\n\n### Configuration Options\n\nThe grid supports various configuration options:\n\n1. **Collection-based Grid**:\n```xml\n\u003cargument name=\"collectionClass\" xsi:type=\"string\"\u003eYour\\Module\\Model\\ResourceModel\\YourCollection\u003c/argument\u003e\n```\n\n2. **SQL-based Grid**:\n```xml\n\u003cargument name=\"tableName\" xsi:type=\"string\"\u003eyour_table_name\u003c/argument\u003e\n```\n\n3. **Field Configuration**:\n```xml\n\u003cargument name=\"fields\" xsi:type=\"array\"\u003e\n    \u003citem name=\"field_name\" xsi:type=\"string\"\u003eField Label\u003c/item\u003e\n\u003c/argument\u003e\n```\n\n4. **Pagination**:\n```xml\n\u003cargument name=\"pageSize\" xsi:type=\"number\"\u003e20\u003c/argument\u003e\n```\n\n5. **Filters**:\n```xml\n\u003cargument name=\"showFilters\" xsi:type=\"boolean\"\u003etrue\u003c/argument\u003e\n```\n\n### Customization\n\n1. **Override Template**:\nCreate your own template at `view/adminhtml/templates/grid/grid-component.phtml`\n\n2. **Custom ViewModel**:\nExtend `GenericViewModelGrid` to add custom functionality:\n```php\n\u003c?php\nnamespace Your\\Module\\ViewModel;\n\nuse Mage\\Grid\\ViewModel\\GenericViewModelGrid;\n\nclass YourCustomViewModel extends GenericViewModelGrid\n{\n    // Add your custom methods here\n}\n```\n\n### Customizing the Grid Component Template\n\nThe module uses a template file at `view/adminhtml/templates/grid/grid-component.phtml` that you can customize. Here are some examples:\n\n1. **Basic Custom Column with Formatter**:\n```php\n\u003c?php\n// In your layout file\n\u003cblock class=\"Mage\\Grid\\Block\\GenericGrid\" name=\"your_grid\"\u003e\n    \u003carguments\u003e\n        \u003cargument name=\"fields\" xsi:type=\"array\"\u003e\n            \u003citem name=\"id\" xsi:type=\"string\"\u003eID\u003c/item\u003e\n            \u003citem name=\"name\" xsi:type=\"string\"\u003eName\u003c/item\u003e\n            \u003citem name=\"status\" xsi:type=\"string\"\u003eStatus\u003c/item\u003e\n        \u003c/argument\u003e\n    \u003c/arguments\u003e\n\u003c/block\u003e\n```\n\n```javascript\n// In your template\nconst grid = new Grid({\n    columns: [\n        'ID',\n        'Name',\n        {\n            name: 'Status',\n            formatter: (cell) =\u003e {\n                const color = cell === 'Active' ? 'green' : 'red';\n                return html`\u003cspan style=\"color: ${color}\"\u003e${cell}\u003c/span\u003e`;\n            }\n        }\n    ],\n    data: [\n        ['1', 'John Doe', 'Active'],\n        ['2', 'Jane Smith', 'Inactive']\n    ],\n    pagination: {\n        enabled: true,\n        limit: 20\n    },\n    sort: true,\n    search: true\n}).render(document.getElementById('wrapper'));\n```\n\n2. **Custom Column with Actions**:\n```javascript\nconst grid = new Grid({\n    columns: [\n        'ID',\n        'Name',\n        {\n            name: 'Actions',\n            formatter: (_, row) =\u003e {\n                const id = row.cells[0].data;\n                return html`\n                    \u003cdiv class=\"actions\"\u003e\n                        \u003cbutton onclick=\"viewItem('${id}')\"\u003eView\u003c/button\u003e\n                        \u003cbutton onclick=\"editItem('${id}')\"\u003eEdit\u003c/button\u003e\n                        \u003cbutton onclick=\"deleteItem('${id}')\"\u003eDelete\u003c/button\u003e\n                    \u003c/div\u003e\n                `;\n            }\n        }\n    ],\n    data: [\n        ['1', 'John Doe'],\n        ['2', 'Jane Smith']\n    ]\n}).render(document.getElementById('wrapper'));\n\n// Add your action functions\nwindow.viewItem = function(id) {\n    // Your view logic\n};\n\nwindow.editItem = function(id) {\n    // Your edit logic\n};\n\nwindow.deleteItem = function(id) {\n    // Your delete logic\n};\n```\n\n3. **Custom Column with Magento UI Components**:\n```javascript\nrequire(['jquery', 'gridjs', 'Magento_Ui/js/modal/alert'], function($, grid, alert) {\n    const gridInstance = new Grid({\n        columns: [\n            'ID',\n            'Name',\n            {\n                name: 'Actions',\n                formatter: (_, row) =\u003e {\n                    const id = row.cells[0].data;\n                    return html`\n                        \u003cbutton onclick=\"showDetails('${id}')\"\u003eDetails\u003c/button\u003e\n                    `;\n                }\n            }\n        ],\n        data: [\n            ['1', 'John Doe'],\n            ['2', 'Jane Smith']\n        ]\n    }).render(document.getElementById('wrapper'));\n\n    window.showDetails = function(id) {\n        alert({\n            title: 'Item Details',\n            content: `Loading details for item ${id}...`,\n            actions: {\n                always: function() {\n                    // Your AJAX logic here\n                }\n            }\n        });\n    };\n});\n```\n\n4. **Custom Column with Dynamic Data Loading**:\n```javascript\nconst grid = new Grid({\n    columns: [\n        'ID',\n        {\n            name: 'Details',\n            formatter: async (_, row) =\u003e {\n                const id = row.cells[0].data;\n                try {\n                    const response = await fetch(`/rest/V1/items/${id}`);\n                    const data = await response.json();\n                    return html`\n                        \u003cdiv class=\"item-details\"\u003e\n                            \u003cstrong\u003e${data.name}\u003c/strong\u003e\n                            \u003cbr/\u003e\n                            \u003csmall\u003e${data.description}\u003c/small\u003e\n                        \u003c/div\u003e\n                    `;\n                } catch (error) {\n                    return html`\u003cspan class=\"error\"\u003eError loading details\u003c/span\u003e`;\n                }\n            }\n        }\n    ],\n    data: [\n        ['1'],\n        ['2']\n    ]\n}).render(document.getElementById('wrapper'));\n```\n\n5. **Custom Column with Form Elements**:\n```javascript\nconst grid = new Grid({\n    columns: [\n        'ID',\n        'Name',\n        {\n            name: 'Status',\n            formatter: (cell, row) =\u003e {\n                const id = row.cells[0].data;\n                return html`\n                    \u003cselect onchange=\"updateStatus('${id}', this.value)\"\u003e\n                        \u003coption value=\"pending\" ${cell === 'pending' ? 'selected' : ''}\u003ePending\u003c/option\u003e\n                        \u003coption value=\"processing\" ${cell === 'processing' ? 'selected' : ''}\u003eProcessing\u003c/option\u003e\n                        \u003coption value=\"complete\" ${cell === 'complete' ? 'selected' : ''}\u003eComplete\u003c/option\u003e\n                    \u003c/select\u003e\n                `;\n            }\n        }\n    ],\n    data: [\n        ['1', 'John Doe', 'pending'],\n        ['2', 'Jane Smith', 'processing']\n    ]\n}).render(document.getElementById('wrapper'));\n\nwindow.updateStatus = function(id, status) {\n    // Your status update logic\n    console.log(`Updating status for ${id} to ${status}`);\n};\n```\n\n6. **Custom Column with Filtering**:\n```javascript\nconst grid = new Grid({\n    columns: [\n        'ID',\n        'Name',\n        {\n            name: 'Status',\n            formatter: (cell) =\u003e {\n                const color = cell === 'Active' ? 'green' : 'red';\n                return html`\u003cspan style=\"color: ${color}\"\u003e${cell}\u003c/span\u003e`;\n            }\n        }\n    ],\n    data: [\n        ['1', 'John Doe', 'Active'],\n        ['2', 'Jane Smith', 'Inactive']\n    ],\n    search: true,\n    pagination: {\n        enabled: true,\n        limit: 20\n    },\n    sort: true,\n    resizable: true\n}).render(document.getElementById('wrapper'));\n\n// Add custom filter handling\ndocument.getElementById('filter-submit').addEventListener('click', function() {\n    const filters = {};\n    document.querySelectorAll('[id^=\"filter-\"]').forEach(input =\u003e {\n        const field = input.id.replace('filter-', '');\n        filters[field] = input.value;\n    });\n    // Your filter logic here\n    console.log('Filters:', filters);\n});\n```\n\n## Security\n\nThe module includes built-in security features:\n- ACL (Access Control List) integration\n- Role-based access control\n- XSS protection\n- CSRF protection\n\n## Support\n\nFor support, please contact:\n- Email: support@mage.com\n- GitHub Issues: [Create an issue](https://github.com/your-repo/mage-grid/issues)\n\n## License\n\nThis module is licensed under the [MIT License](LICENSE).\n\n## Contributing\n\nContributions are welcome! Please feel free to submit a Pull Request.\n\n# Magento 2 Data GridsJS\n**GridJS** and **DataTable** integration with Magento 2\n\nGrid.js(https://gridjs.io/) is a Free and open-source JavaScript table plugin. It works with most JavaScript frameworks, including React, Angular, Vue and VanillaJs.\n\nGrid.js uses Preact to render the elements and that means that you can take advantage of Preact's Virtual DOM and render complex cells.\n\n**DataTable** integration with magento \n\n**DataTables** (https://datatables.net/) is a Javascript HTML table-enhancing library. It is a highly flexible tool, built upon the foundations of progressive enhancement, that adds all of these advanced features to any HTML table.\n\nAt First, GridJS was integrated, but after DataTable was added. \n\nAll extensions come as jQuery plugins but can work independently. \n\nI also have **AG Grid** integration for Magento 2 but it is not part of this open source solution.\nThe Best JavaScript Grid in the World\nThe professional choice for developers building enterprise applications\n\nThis and all other magento extensions based on this revolutionary extension:\nhttps://github.com/Genaker/reactmagento2\nit allows running magento without MAgento broken JS and uses better modern solutions \n\n# Installation:\n```\ncomposer require mage/gridjs\n```\n# usage in Admin Area:\n```\nrequire(['jquery','gridjs']){() =\u003e\njQuery('#lastOrdersGrid_table').Grid()\n}\n```\nExamples:\nAfter installation, examples will be embedded at the bottom of the admin dashboard \n\n![image](https://github.com/Genaker/magento_gridjs/assets/9213670/f5a78899-35be-40be-bfd9-dc3385c56548)\n\n![image](https://github.com/Genaker/magento_gridjs/assets/9213670/f0c58b87-f588-4dfa-b576-c5811aa7df46)\n\n## Source code of the grid\n\n```\n\u003ch1\u003e Grid JS\u003c/h1\u003e\n\n\u003cscript type=\"module\"\u003e\n//Modern libs don't work with this magento shit so we are using import.\nimport { html } from 'preact';\n\nrequire(['jquery', 'gridjs'], function($, grid) {\n  jQuery(\"div#myTable\").Grid({\n    columns: ['Name', 'Email', 'Phone Number' , { \n        name: 'Actions',\n        formatter: (_, row) =\u003e html`\u003ca href=\".\"\u003e\u003cbutton\u003e EDIT \u003c/button\u003e\u003c/a\u003e`\n      }\n      ],\n    pagination: {\n    limit: 2\n    },\n    search: true,\n    sort: true,\n    resizable: true,\n    data: [\n      ['John', 'john@example.com', '(353) 01 222 3333'],\n      ['Mark', 'mark@gmail.com',   '(01) 22 888 4444'],\n      ['Egor', 'egorshitikov@gmail.com',   '\u003cspan\u003eNONE \u003c/span\u003e']\n    ]\n  });\n})\n\u003c/script\u003e\n\n\u003cdiv id=\"myTable\"\u003e\u003c/div\u003e\n\n\u003ch1\u003e DataTable \u003c/h1\u003e\n\u003cscript\u003e\n\nrequire(['jquery', 'DataTable'], function($) {\n  var dataSet = [\n    ['Tiger Nixon', 'System Architect', 'Edinburgh', '5421', '2011/04/25', '$320,800'],\n    ['Garrett Winters', 'Accountant', 'Tokyo', '8422', '2011/07/25', '$170,750'],\n  ....\n];\n \n$('#example').DataTable({\n    columns: [\n        { title: 'Name' },\n        { title: 'Position' },\n        { title: 'Office' },\n        { title: 'Extn.' },\n        { title: 'Start date' },\n        { title: 'Salary' }\n    ],\n    data: dataSet\n});\n})\n\n\u003c/script\u003e\n\n\n\u003ctable id=\"example\" class=\"display\" width=\"100%\"\u003e\u003c/table\u003e\n```\n# More Examples GridJS\n\n## In this examples, we load the data from an existing HTML table\n\nGrid.js can also convert an HTML table. Simply select the table with jQuery and call Grid:\n\n$(\"table#myTable\").Grid();\n\nYou can pass all Grid.js configs to the Grid function. See Grid.js Config for more details.\n\n##  HTML in cells \n\nThen you can use that in formatter function or directly in data array:\n\n\n```\nconst grid = new Grid({\n  columns: [\n      { \n        name: 'Name',\n        formatter: (cell) =\u003e html`\u003cb\u003e${cell}\u003c/b\u003e`\n      },\n      'Email',\n      { \n        name: 'Actions',\n        formatter: (_, row) =\u003e html`\u003ca href='mailto:${row.cells[1].data}'\u003eEmail\u003c/a\u003e`\n      },\n   ],\n  data: Array(5).fill().map(x =\u003e [\n    faker.name.findName(),\n    faker.internet.email(),\n    null\n  ])\n});\n```\n\n## Import server-side data\nYou can use the server property to load data from a remote server and populate the table:\n\n```\nconst grid = new Grid({\n  columns: ['Name', 'Language', 'Released At', 'Artist'],\n  server: {\n    url: 'https://api.scryfall.com/cards/search?q=Inspiring',\n    then: data =\u003e data.data.map(card =\u003e [card.name, card.lang, card.released_at, card.artist])\n  } \n});\n```\n\n## Server Side Pagination\nAdd server property to the pagination config to enable server-side pagination. Also, make sure the total property is correctly defined in the main server config block\n\n```\nconst grid = new Grid({\n  columns: ['Pokemon', 'URL'],\n  pagination: {\n    limit: 5,\n    server: {\n      url: (prev, page, limit) =\u003e `${prev}?limit=${limit}\u0026offset=${page * limit}`\n    }\n  },\n  server: {\n    url: 'https://pokeapi.co/api/v2/pokemon',\n    then: data =\u003e data.results.map(pokemon =\u003e [\n      pokemon.name, html(`\u003ca href='${pokemon.url}'\u003eLink to ${pokemon.name}\u003c/a\u003e`)\n    ]),\n    total: data =\u003e data.count\n  } \n});\n```\n\n# DataTable example \n\n## Loading data\nAjax data is loaded by DataTables simply by using the ajax option to set the URL for where the Ajax request should be made. For example, the following shows a minimal configuration with Ajax sourced data:\n\n```\n$('#myTable').DataTable( {\n    ajax: '/api/myData'\n} );\n```\n\n## JSON data source\n\nWhen considering Ajax loaded data for DataTables we almost always are referring to a JSON payload - i.e. the data that is returned from the server is in a JSON data structure. This is because the JSON is derived from Javascript and it therefore naturally plays well with Javascript libraries such as DataTables.\n\n## Non-jQuery options\nIf you are initialising DataTables through the new DataTable() option available in DataTables 1.11, you can pass configuration options in using the second parameter of the constructor:\n\n```\nnew DataTable( '#example', {\n    paging: false,\n    scrollY: 400\n} );\n```\n\n## Data rendering\nData within DataTables can be easily rendered to add graphics or colour to your tables, as demonstrated in the example on this page. These examples make use of columns.render to customise the cells in three ways:\n![image](https://github.com/Genaker/magento_gridjs/assets/9213670/cb87d61b-e38b-46f4-8b97-f959ac55efd8)\n```\n$('#example').DataTable({\n    ajax: '../ajax/data/objects_salary.txt',\n    columns: [\n        {\n            data: 'name'\n        },\n        {\n            data: 'position',\n            render: function (data, type) {\n                if (type === 'display') {\n                    let link = 'https://datatables.net';\n \n                    if (data[0] \u003c 'H') {\n                        link = 'https://cloudtables.com';\n                    }\n                    else if (data[0] \u003c 'S') {\n                        link = 'https://editor.datatables.net';\n                    }\n \n                    return '\u003ca href=\"' + link + '\"\u003e' + data + '\u003c/a\u003e';\n                }\n \n                return data;\n            }\n        },\n        {\n            className: 'f32', // used by world-flags-sprite library\n            data: 'office',\n            render: function (data, type) {\n                if (type === 'display') {\n                    let country = '';\n \n                    switch (data) {\n                        case 'Argentina':\n                            country = 'ar';\n                            break;\n                        case 'Edinburgh':\n                            country = '_Scotland';\n                            break;\n                        case 'London':\n                            country = '_England';\n                            break;\n                        case 'New York':\n                        case 'San Francisco':\n                            country = 'us';\n                            break;\n                        case 'Sydney':\n                            country = 'au';\n                            break;\n                        case 'Tokyo':\n                            country = 'jp';\n                            break;\n                    }\n \n                    return '\u003cspan class=\"flag ' + country + '\"\u003e\u003c/span\u003e ' + data;\n                }\n \n                return data;\n            }\n        },\n        {\n            data: 'extn',\n            render: function (data, type, row, meta) {\n                return type === 'display'\n                    ? '\u003cprogress value=\"' + data + '\" max=\"9999\"\u003e\u003c/progress\u003e'\n                    : data;\n            }\n        },\n        {\n            data: 'start_date'\n        },\n        {\n            data: 'salary',\n            render: function (data, type) {\n                var number = $.fn.dataTable.render\n                    .number(',', '.', 2, '$')\n                    .display(data);\n \n                if (type === 'display') {\n                    let color = 'green';\n                    if (data \u003c 250000) {\n                        color = 'red';\n                    }\n                    else if (data \u003c 500000) {\n                        color = 'orange';\n                    }\n \n                    return (\n                        '\u003cspan style=\"color:' +\n                        color +\n                        '\"\u003e' +\n                        number +\n                        '\u003c/span\u003e'\n                    );\n                }\n \n                return number;\n            }\n        }\n    ]\n});\n```\n\n## Data Processors System\n\nMage Grid uses a flexible and extensible **data processor** system to transform and format grid cell values before rendering. This allows you to easily customize how each field is displayed, including adding HTML, formatting dates, prices, statuses, and more.\n\n### Dual Processor Configuration\n\nThe module supports two ways to configure data processors:\n\n1. **Layout XML Configuration** (`grid_grid_index.xml`):\n```xml\n\u003cblock class=\"Mage\\Grid\\Block\\GenericGrid\" name=\"grid_generic_grid\" template=\"Mage_Grid::grid/grid-component.phtml\"\u003e\n    \u003carguments\u003e\n        \u003cargument name=\"dataProcessors\" xsi:type=\"array\"\u003e\n            \u003citem name=\"status\" xsi:type=\"object\"\u003eMage\\Grid\\Model\\DataProcessor\\StatusProcessor\u003c/item\u003e\n            \u003citem name=\"grand_total\" xsi:type=\"object\"\u003eMage\\Grid\\Model\\DataProcessor\\PriceProcessor\u003c/item\u003e\n        \u003c/argument\u003e\n    \u003c/arguments\u003e\n\u003c/block\u003e\n```\n\n2. **DI Configuration** (`di.xml`):\n```xml\n\u003ctype name=\"Mage\\Grid\\ViewModel\\GenericViewModelGrid\"\u003e\n    \u003carguments\u003e\n        \u003cargument name=\"dataProcessors\" xsi:type=\"array\"\u003e\n            \u003citem name=\"customer_email\" xsi:type=\"object\"\u003eMage\\Grid\\Model\\DataProcessor\\ObfuscateProcessor\u003c/item\u003e\n            \u003citem name=\"created_at\" xsi:type=\"object\"\u003eMage\\Grid\\Model\\DataProcessor\\DateProcessor\u003c/item\u003e\n            \u003citem name=\"grand_total\" xsi:type=\"object\"\u003eMage\\Grid\\Model\\DataProcessor\\PriceProcessor\u003c/item\u003e\n        \u003c/argument\u003e\n    \u003c/arguments\u003e\n\u003c/type\u003e\n```\n\n### Processor Resolution Order\n\n1. Layout XML processors take precedence over DI configuration\n2. If no processor is found in either location, the default processor is used\n3. Processors can be chained using the `ChainProcessor`\n\n### Example: Combined Configuration\n\n```xml\n\u003c!-- grid_grid_index.xml --\u003e\n\u003cblock class=\"Mage\\Grid\\Block\\GenericGrid\" name=\"grid_generic_grid\"\u003e\n    \u003carguments\u003e\n        \u003cargument name=\"dataProcessors\" xsi:type=\"array\"\u003e\n            \u003c!-- Grid-specific processors --\u003e\n            \u003citem name=\"status\" xsi:type=\"object\"\u003eMage\\Grid\\Model\\DataProcessor\\StatusProcessor\u003c/item\u003e\n        \u003c/argument\u003e\n    \u003c/arguments\u003e\n\u003c/block\u003e\n\n\u003c!-- di.xml --\u003e\n\u003ctype name=\"Mage\\Grid\\ViewModel\\GenericViewModelGrid\"\u003e\n    \u003carguments\u003e\n        \u003cargument name=\"dataProcessors\" xsi:type=\"array\"\u003e\n            \u003c!-- Global processors --\u003e\n            \u003citem name=\"customer_email\" xsi:type=\"object\"\u003eMage\\Grid\\Model\\DataProcessor\\ObfuscateProcessor\u003c/item\u003e\n            \u003citem name=\"created_at\" xsi:type=\"object\"\u003eMage\\Grid\\Model\\DataProcessor\\DateProcessor\u003c/item\u003e\n        \u003c/argument\u003e\n    \u003c/arguments\u003e\n\u003c/type\u003e\n```\n\n### Processor Types\n\n1. **Default Processors**:\n   - `DefaultProcessor`: Basic HTML escaping\n   - `StatusProcessor`: Status badge rendering\n   - `PriceProcessor`: Price formatting\n   - `DateProcessor`: Date/time formatting\n   - `ObfuscateProcessor`: Data obfuscation\n\n2. **Custom Processors**:\n   - Implement `Mage\\Grid\\Api\\DataProcessorInterface`\n   - Register in either layout XML or DI configuration\n   - Can be grid-specific or global\n\n### Example: Custom Processor\n\n```php\nnamespace Your\\Module\\Model\\DataProcessor;\n\nuse Mage\\Grid\\Api\\DataProcessorInterface;\n\nclass CustomProcessor implements DataProcessorInterface\n{\n    public function process($field, $value, $row)\n    {\n        // Your custom processing logic\n        return $processedValue;\n    }\n}\n```\n\n### Chain Processor\n\nThe `ChainProcessor` allows you to combine multiple processors:\n\n```xml\n\u003ctype name=\"Mage\\Grid\\Model\\DataProcessor\\ChainProcessor\"\u003e\n    \u003carguments\u003e\n        \u003cargument name=\"processors\" xsi:type=\"array\"\u003e\n            \u003citem name=\"escape\" xsi:type=\"object\"\u003eMage\\Grid\\Model\\DataProcessor\\DefaultProcessor\u003c/item\u003e\n            \u003citem name=\"format\" xsi:type=\"object\"\u003eMage\\Grid\\Model\\DataProcessor\\PriceProcessor\u003c/item\u003e\n        \u003c/argument\u003e\n    \u003c/arguments\u003e\n\u003c/type\u003e\n```\n\n### Best Practices\n\n1. Use layout XML processors for grid-specific customizations\n2. Use DI configuration for global processors\n3. Keep processors focused on a single responsibility\n4. Use the chain processor for complex transformations\n5. Document processor behavior and dependencies\n\n## Additional HTML/JS Templates (Popups, Custom Scripts, etc.)\n\nMage Grid allows you to inject additional HTML or JavaScript into your grid page using configurable template files. This is useful for adding custom popups, event handlers, or any extra markup/scripts you need for your grid.\n\n### How to Use\n\n1. **Create your additional template(s):**\n   - Place your custom HTML/JS in `.phtml` files, e.g.:\n     - `view/adminhtml/templates/grid/additional-html.phtml`\n     - `view/adminhtml/templates/grid/another-additional-html.phtml`\n\n2. **Configure in layout XML:**\n   - You can specify one or more additional templates using the `additional_html_templates` argument:\n   ```xml\n   \u003cblock class=\"Mage\\Grid\\Block\\GenericGrid\" name=\"your.grid.block\" template=\"Mage_Grid::grid/grid-component.phtml\"\u003e\n       \u003carguments\u003e\n           \u003cargument name=\"additional_html_templates\" xsi:type=\"array\"\u003e\n               \u003citem name=\"popupJS\" xsi:type=\"string\"\u003eMage_Grid::grid/additional-html.phtml\u003c/item\u003e\n               \u003citem name=\"custom2\" xsi:type=\"string\"\u003eMage_Grid::grid/another-additional-html.phtml\u003c/item\u003e\n           \u003c/argument\u003e\n       \u003c/arguments\u003e\n   \u003c/block\u003e\n   ```\n   - The block will render each template in order. If a template is missing, an error message will be shown for that template.\n\n3. **Access in your main grid template:**\n   - In your main grid template (e.g. `grid-component.phtml`), output the additional HTML:\n   ```php\n   \u003c?= $block-\u003egetAditionalHTML() ?\u003e\n   ```\n\n### Example: Popup Event Handler Integration\n\nIf you want to add a popup that shows row details when a status badge is clicked, your `additional-html.phtml` might look like:\n\n```html\n\u003cscript\u003e\n\n// Re-attach after every Grid.js update\nif (window.grid) {\n    grid.on('ready', attachStatusBadgePopup);\n    grid.on('update', attachStatusBadgePopup);\n}\n\u003c/script\u003e\n```\n\n**Important:**\n- If your grid data is updated dynamically (e.g. via AJAX or Grid.js), you must re-attach event handlers after each update. The above example does this using Grid.js events.\n- You can include as many additional templates as you need, and each can contain its own scripts or markup.\n\n### Error Handling\n- If a specified template does not exist, a user-friendly error message will be shown in the grid output.\n\n## Filter Types\n\nThe Mage Grid module supports several types of filters that can be configured via layout XML:\n\n### Available Filter Types\n\n1. **Text Input Filter**\n```xml\n\u003citem name=\"customer_email\" xsi:type=\"array\"\u003e\n    \u003citem name=\"label\" xsi:type=\"string\"\u003eEmail\u003c/item\u003e\n    \u003citem name=\"element\" xsi:type=\"string\"\u003etext\u003c/item\u003e\n\u003c/item\u003e\n```\n- Default filter type\n- Supports partial matching\n- Auto-applies on input change\n- Supports Enter key for immediate filtering\n\n2. **Select Filter**\n```xml\n\u003citem name=\"status\" xsi:type=\"array\"\u003e\n    \u003citem name=\"label\" xsi:type=\"string\"\u003eStatus\u003c/item\u003e\n    \u003citem name=\"element\" xsi:type=\"string\"\u003eselect\u003c/item\u003e\n    \u003citem name=\"source_model\" xsi:type=\"string\"\u003eYour\\Module\\Model\\Source\\Status\u003c/item\u003e\n\u003c/item\u003e\n```\n- Single-value selection\n- Dropdown interface\n- Supports custom source models\n- \"Any\" option included by default\n\n3. **Multiselect Filter**\n```xml\n\u003citem name=\"store_id\" xsi:type=\"array\"\u003e\n    \u003citem name=\"label\" xsi:type=\"string\"\u003eStore\u003c/item\u003e\n    \u003citem name=\"element\" xsi:type=\"string\"\u003emultiselect\u003c/item\u003e\n    \u003citem name=\"source_model\" xsi:type=\"string\"\u003eYour\\Module\\Model\\Source\\Store\u003c/item\u003e\n\u003c/item\u003e\n```\n- Multiple value selection\n- Searchable dropdown\n- Supports Ctrl/Cmd for multiple selections\n- \"Any\" option for clearing selection\n- Built-in search functionality\n- Maintains selected state in URL\n\n### Filter Features\n\n- **Caching**: \n  - Filter values are cached for better performance\n  - Cache is applied for results \u003e 100 items\n  - 24-hour cache lifetime for filter options\n  - Cache is tagged for easy management\n\n- **URL Integration**:\n  - Filter states are maintained in URL parameters\n  - Supports browser back/forward navigation\n  - Bookmarkable filtered states\n  - Clear all filters functionality\n\n- **UI/UX Features**:\n  - Responsive design\n  - Mobile-friendly dropdowns\n  - Clear visual feedback\n  - Consistent styling with Magento admin\n  - Tooltip hints for usage\n\n### Example Configuration\n\nFull example of filter configuration in layout XML:\n```xml\n\u003cargument name=\"fields\" xsi:type=\"array\"\u003e\n    \u003c!-- Text Filter --\u003e\n    \u003citem name=\"increment_id\" xsi:type=\"array\"\u003e\n        \u003citem name=\"label\" xsi:type=\"string\"\u003eOrder #\u003c/item\u003e\n        \u003citem name=\"element\" xsi:type=\"string\"\u003etext\u003c/item\u003e\n    \u003c/item\u003e\n    \n    \u003c!-- Select Filter --\u003e\n    \u003citem name=\"status\" xsi:type=\"array\"\u003e\n        \u003citem name=\"label\" xsi:type=\"string\"\u003eStatus\u003c/item\u003e\n        \u003citem name=\"element\" xsi:type=\"string\"\u003eselect\u003c/item\u003e\n        \u003citem name=\"source_model\" xsi:type=\"string\"\u003eMagento\\Sales\\Model\\Order\\Config\u003c/item\u003e\n    \u003c/item\u003e\n    \n    \u003c!-- Multiselect Filter --\u003e\n    \u003citem name=\"store_id\" xsi:type=\"array\"\u003e\n        \u003citem name=\"label\" xsi:type=\"string\"\u003eStore View\u003c/item\u003e\n        \u003citem name=\"element\" xsi:type=\"string\"\u003emultiselect\u003c/item\u003e\n        \u003citem name=\"source_model\" xsi:type=\"string\"\u003eMagento\\Store\\Model\\System\\Store\u003c/item\u003e\n    \u003c/item\u003e\n\u003c/argument\u003e\n```\n\n### Custom Source Model\n\nExample of a custom source model for filters:\n```php\nnamespace Your\\Module\\Model\\Source;\n\nuse Mage\\Grid\\Model\\Fields\\DataSourceInterface;\nuse Magento\\Framework\\App\\ResourceConnection;\n\nclass CustomSource implements DataSourceInterface\n{\n    protected $resource;\n    \n    public function __construct(ResourceConnection $resource)\n    {\n        $this-\u003eresource = $resource;\n    }\n\n    public function getValues($field)\n    {\n        // Your custom logic to fetch values\n        return ['value1', 'value2', 'value3'];\n    }\n}\n```\n\n### JavaScript Events\n\nThe grid filters emit several events that you can listen to:\n```javascript\n// Filter change event\ndocument.addEventListener('grid:filter:change', function(event) {\n    console.log('Filter changed:', event.detail);\n});\n\n// Filter clear event\ndocument.addEventListener('grid:filter:clear', function(event) {\n    console.log('Filters cleared');\n});\n```\n\n## Replacing GridJS with Alternative Grid Systems\n\nThe Mage Grid module is designed to be flexible and allows you to replace GridJS with any other grid system. Here's how to implement alternative grid solutions:\n\n### 1. DataTables Integration\n\nTo use DataTables instead of GridJS:\n\n1. **Create a new template** (`view/adminhtml/templates/grid/datatable-component.phtml`):\n```php\n\u003c?php\n// Get grid data\n$fields = array_keys($block-\u003egetFieldsNames());\n$fieldsFull = $block-\u003egetFields();\n$jsonGridData = $block-\u003egetGridJsonData();\n$fieldsConfig = $block-\u003egetFieldsConfig();\n$tableName = $block-\u003egetTableName();\n$fieldsNames = $block-\u003egetFieldsNames();\n$filters = $this-\u003egetRequest()-\u003egetParam('filter', []);\n$processedFields = $block-\u003egetProcessedFields($fields, $fieldsConfig, $filters);\n?\u003e\n\n\u003cdiv id=\"grid-wrapper\"\u003e\n    \u003c!-- Render filters --\u003e\n    \u003c?= $block-\u003egetFiltersHtml(['fields' =\u003e $processedFields, 'filters' =\u003e $filters]) ?\u003e\n\n    \u003c!-- DataTables container --\u003e\n    \u003ctable id=\"grid-table\" class=\"display\"\u003e\n        \u003cthead\u003e\n            \u003ctr\u003e\n                \u003c?php foreach ($fieldsNames as $field =\u003e $label): ?\u003e\n                    \u003cth\u003e\u003c?= $label ?\u003e\u003c/th\u003e\n                \u003c?php endforeach; ?\u003e\n            \u003c/tr\u003e\n        \u003c/thead\u003e\n    \u003c/table\u003e\n\u003c/div\u003e\n\n\u003cscript\u003e\nrequire(['jquery', 'datatables'], function($) {\n    $('#grid-table').DataTable({\n        processing: true,\n        serverSide: true,\n        ajax: {\n            url: window.location.href,\n            data: function(d) {\n                d.data = true;\n                return d;\n            }\n        },\n        columns: \u003c?= json_encode(array_map(function($field) use ($fieldsNames) {\n            return ['data' =\u003e $field, 'title' =\u003e $fieldsNames[$field]];\n        }, $fields)) ?\u003e,\n        pageLength: 20,\n        order: [[0, 'desc']]\n    });\n});\n\u003c/script\u003e\n```\n\n2. **Update your layout XML** to use the new template:\n```xml\n\u003cblock class=\"Mage\\Grid\\Block\\GenericGrid\" \n       name=\"grid_generic_grid\" \n       template=\"Mage_Grid::grid/datatable-component.phtml\"\u003e\n    \u003c!-- ... existing arguments ... --\u003e\n\u003c/block\u003e\n```\n\n### 2. Simple HTML Table\n\nFor a basic HTML table without JavaScript:\n\n1. **Create a new template** (`view/adminhtml/templates/grid/simple-table.phtml`):\n```php\n\u003c?php\n$fields = array_keys($block-\u003egetFieldsNames());\n$fieldsFull = $block-\u003egetFields();\n$data = $block-\u003egetViewModel()-\u003egetGridData();\n$fieldsConfig = $block-\u003egetFieldsConfig();\n$fieldsNames = $block-\u003egetFieldsNames();\n$filters = $this-\u003egetRequest()-\u003egetParam('filter', []);\n$processedFields = $block-\u003egetProcessedFields($fields, $fieldsConfig, $filters);\n?\u003e\n\n\u003cdiv id=\"grid-wrapper\"\u003e\n    \u003c!-- Render filters --\u003e\n    \u003c?= $block-\u003egetFiltersHtml(['fields' =\u003e $processedFields, 'filters' =\u003e $filters]) ?\u003e\n\n    \u003c!-- Simple HTML table --\u003e\n    \u003ctable class=\"data-grid\"\u003e\n        \u003cthead\u003e\n            \u003ctr\u003e\n                \u003c?php foreach ($fieldsNames as $field =\u003e $label): ?\u003e\n                    \u003cth\u003e\u003c?= $label ?\u003e\u003c/th\u003e\n                \u003c?php endforeach; ?\u003e\n            \u003c/tr\u003e\n        \u003c/thead\u003e\n        \u003ctbody\u003e\n            \u003c?php foreach ($data as $row): ?\u003e\n                \u003ctr\u003e\n                    \u003c?php foreach ($fields as $field): ?\u003e\n                        \u003ctd\u003e\u003c?= $block-\u003egetViewModel()-\u003eprocessField($field, $row[$field], $row) ?\u003e\u003c/td\u003e\n                    \u003c?php endforeach; ?\u003e\n                \u003c/tr\u003e\n            \u003c?php endforeach; ?\u003e\n        \u003c/tbody\u003e\n    \u003c/table\u003e\n\n    \u003c!-- Simple pagination --\u003e\n    \u003c?php if ($block-\u003egetViewModel()-\u003egetTotalPages() \u003e 1): ?\u003e\n        \u003cdiv class=\"pagination\"\u003e\n            \u003c?php for ($i = 1; $i \u003c= $block-\u003egetViewModel()-\u003egetTotalPages(); $i++): ?\u003e\n                \u003ca href=\"?page=\u003c?= $i ?\u003e\" \n                   class=\"\u003c?= $i == $block-\u003egetViewModel()-\u003egetCurrentPage() ? 'active' : '' ?\u003e\"\u003e\n                    \u003c?= $i ?\u003e\n                \u003c/a\u003e\n            \u003c?php endfor; ?\u003e\n        \u003c/div\u003e\n    \u003c?php endif; ?\u003e\n\u003c/div\u003e\n```\n\n### 3. Custom Grid System\n\nTo implement your own grid system:\n\n1. **Create a new template** with your preferred grid library\n2. **Use the block's methods** to get data and configuration:\n   - `getFieldsNames()`: Get field labels\n   - `getGridJsonData()`: Get grid data as JSON\n   - `getFieldsConfig()`: Get field configurations\n   - `getProcessedFields()`: Get processed field data\n   - `getFiltersHtml()`: Get rendered filters\n\n3. **Implement your own JavaScript** to handle:\n   - Data loading\n   - Pagination\n   - Sorting\n   - Filtering\n\n### Key Components to Override\n\nWhen replacing GridJS, you mainly need to focus on:\n\n1. **Template File**: Create your own `grid-component.phtml`\n2. **JavaScript**: Implement your grid initialization\n3. **CSS**: Add your grid styling\n4. **Data Processing**: Use the existing processor system\n\nThe rest of the module (data loading, filtering, processing) remains unchanged.\n\n### Example: Using AG Grid\n\n```php\n\u003c!-- view/adminhtml/templates/grid/ag-grid-component.phtml --\u003e\n\u003cdiv id=\"grid-wrapper\"\u003e\n    \u003c?= $block-\u003egetFiltersHtml($filterData) ?\u003e\n    \u003cdiv id=\"myGrid\" style=\"height: 500px; width: 100%;\"\u003e\u003c/div\u003e\n\u003c/div\u003e\n\n\u003cscript\u003e\nrequire(['ag-grid-community'], function(agGrid) {\n    const columnDefs = \u003c?= json_encode(array_map(function($field) use ($fieldsNames) {\n        return {\n            field: $field,\n            headerName: $fieldsNames[$field]\n        };\n    }, $fields)) ?\u003e;\n\n    const gridOptions = {\n        columnDefs: columnDefs,\n        rowData: \u003c?= $jsonGridData ?\u003e,\n        pagination: true,\n        paginationPageSize: 20,\n        onGridReady: params =\u003e {\n            params.api.sizeColumnsToFit();\n        }\n    };\n\n    new agGrid.Grid(document.querySelector('#myGrid'), gridOptions);\n});\n\u003c/script\u003e\n```\n\n### Best Practices\n\n1. **Keep Data Processing**: Use the existing processor system for consistent data formatting\n2. **Maintain Filter Integration**: Keep the filter system for consistent filtering\n3. **Preserve Field Configuration**: Use the existing field configuration system\n4. **Handle Server-Side Operations**: Implement proper server-side pagination and filtering\n5. **Maintain Responsiveness**: Ensure your grid works well on all devices\n\n## Performance Monitoring \u0026 Optimization\n\nThe module includes built-in performance metrics to help you monitor and optimize your grid's performance:\n\n### Performance Metrics Panel\n\nThe grid displays real-time performance metrics including:\n- Server SQL Query time\n- Server Count time\n- AJAX Response time\n- Total processing time\n\nThese metrics are displayed in the performance panel below the grid and are color-coded:\n- Green: Normal performance\n- Red: Performance issues detected (\u003e1 second)\n\n### Performance Optimization\n\nIf you notice performance issues (red indicators), here are some steps to optimize:\n\n1. **Query Optimization**\n   - Review your SQL queries using the Magento profiler\n   - Add appropriate indexes to frequently filtered columns\n   - Consider implementing query caching\n\n2. **Data Loading**\n   - Implement server-side pagination\n   - Use lazy loading for large datasets\n   - Consider implementing data caching\n\n3. **Grid Configuration**\n   - Reduce the number of columns if possible\n   - Use efficient column formatters\n   - Implement proper filtering strategies\n\n### AI-Powered Optimization\n\nFor advanced optimization, you can ask our AI assistant:\n```\n\"Analyze my grid performance and suggest optimizations for [specific issue]\"\n```\n\nThe AI will:\n- Analyze your current configuration\n- Review performance metrics\n- Suggest specific optimizations\n- Provide code examples for implementation\n\nAI will provide specific recommendations based on your metrics\n\n\n**Remember: Regular performance monitoring and optimization is key to maintaining a responsive and efficient grid system.**\n\n## API Endpoints\n\nThe module provides REST API endpoints for accessing grid data programmatically:\n\n### Available Endpoints\n\n1. **Get Grid Data**\n   ```\n   GET /V1/grid/:gridId/data\n   ```\n   Parameters:\n   - `gridId`: Identifier of the grid\n   - `filters`: Array of filter criteria (optional)\n   - `page`: Page number (default: 1)\n   - `pageSize`: Items per page (default: 20)\n\n   Response:\n   ```json\n   {\n     \"data\": [\n       {\n         \"id\": \"1\",\n         \"name\": \"Example\",\n         \"created_at\": \"2024-01-01 12:00:00\"\n       }\n     ],\n     \"total_count\": 100,\n     \"performance_metrics\": {\n       \"execution_time\": 150,\n       \"sql_time\": 100,\n       \"count_time\": 50\n     }\n   }\n   ```\n\n2. **Get Grid Configuration**\n   ```\n   GET /V1/grid/:gridId/config\n   ```\n   Returns the grid's configuration including:\n   - Column definitions\n   - Default settings\n   - Available filters\n\n3. **Get Grid Fields**\n   ```\n   GET /V1/grid/:gridId/fields\n   ```\n   Returns the list of available fields and their configurations.\n\n4. **Get Grid Filters**\n   ```\n   GET /V1/grid/:gridId/filters\n   ```\n   Returns the available filter options for the grid.\n\n### Authentication\n\nAll API endpoints require authentication using Magento's standard authentication methods:\n- OAuth 2.0\n- Integration tokens\n- Admin tokens\n\n### Example Usage\n\n```php\n// Using PHP\n$client = new \\Magento\\Framework\\HTTP\\Client\\Curl();\n$client-\u003eaddHeader('Authorization', 'Bearer ' . $token);\n$client-\u003eget('https://your-store.com/rest/V1/grid/orders/data?page=1\u0026pageSize=20');\n\n// Using JavaScript\nfetch('/rest/V1/grid/orders/data?page=1\u0026pageSize=20', {\n    headers: {\n        'Authorization': 'Bearer ' + token\n    }\n})\n.then(response =\u003e response.json())\n.then(data =\u003e console.log(data));\n```\n\n### Performance Monitoring\n\nThe API response includes performance metrics to help monitor and optimize grid performance:\n- `execution_time`: Total time taken to process the request\n- `sql_time`: Time taken for SQL queries\n- `count_time`: Time taken for count operations\n\n### Error Handling\n\nThe API uses standard HTTP status codes and returns detailed error messages:\n```json\n{\n    \"message\": \"Error retrieving grid data: [specific error]\",\n    \"trace\": \"Stack trace for debugging\"\n}\n```\n\n### Rate Limiting\n\nTo protect the server, API requests are rate-limited:\n- 100 requests per minute per IP\n- 1000 requests per hour per user\n\n### Best Practices\n\n1. **Caching**\n   - Cache responses when possible\n   - Use ETags for conditional requests\n   - Implement client-side caching\n\n2. **Pagination**\n   - Always use pagination for large datasets\n   - Keep page size reasonable (20-50 items)\n   - Use cursor-based pagination for large datasets\n\n3. **Filtering**\n   - Use specific filters to reduce data size\n   - Combine multiple filters when needed\n   - Cache common filter combinations\n\n4. **Error Handling**\n   - Implement proper error handling\n   - Use exponential backoff for retries\n   - Log errors for monitoring\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgenaker%2Fmagento_gridjs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgenaker%2Fmagento_gridjs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgenaker%2Fmagento_gridjs/lists"}