How to Create Admin Grid in Magento 2
Magento 2 grids are a way to list the items in a database table for better management. The grid allows to sort, filter, edit, and update the data.
By default, Magento 2 offers order grid, product grid, review grid, etc. However, these default grids fall short when you require to create a custom grid to manage and show database items of the custom module.
The solution is to create admin grid in Magento 2! It allows creating and displaying the order or customer data in table format in the custom module as per the users’ requirements. Moreover, it also allows to remove column from admin grid Dynamically from the table, providing a more customized and streamlined view of the data. Likewise you will also need to create admin menu in Magento 2 to access any custom page in admin panel.
There are two ways to create admin grid in Magento 2 programmatically- using the block and component. Check both the methods in this post.
Method to Create Admin Grid in Magento 2 Using the Block:
Create Block file [Vendor]\[Module]\Block\Adminhtml\Grid\Grid.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 |
namespace [Vendor]\[Module]\Block\Adminhtml\Grid; use Magento\Backend\Block\Widget\Grid\Extended; use Magento\Backend\Block\Template\Context; use Magento\Backend\Helper\Data; use Magento\Framework\Registry; use Magento\Framework\ObjectManagerInterface; use [Vendor]\[Module]\Model\ResourceModel\Demo\CollectionFactory as DemoCollection; // also you can use Magento Default CollectionFactory class Grid extends Extended { protected $registry; protected $_objectManager = null; protected $demoFactory; public function __construct( Context $context, Data $backendHelper, Registry $registry, ObjectManagerInterface $objectManager, DemoCollection $demoFactory, array $data = [] ) { $this->_objectManager = $objectManager; $this->registry = $registry; $this -> demoFactory = $demoFactory; parent::__construct($context, $backendHelper, $data); } protected function _construct() { parent::_construct(); $this->setId('index'); $this->setDefaultSort('created_at'); $this->setDefaultDir('DESC'); $this->setSaveParametersInSession(true); } protected function _prepareCollection() { $demo = $this->demoFactory->create() ->addFieldToSelect('*'); $demo->addFieldToFilter('id', array('neq' => '')); $this->setCollection($demo); return parent::_prepareCollection(); } protected function _prepareColumns() { $this->addColumn( 'id', [ 'header_css_class' => 'a-center', 'type' => 'checkbox', 'name' => 'id', 'align' => 'center', 'index' => 'id', ] ); $this->addColumn( 'id', [ 'header' => __('ID'), 'type' => 'number', 'index' => 'id', 'header_css_class' => 'col-id', 'column_css_class' => 'col-id', ] ); $this->addColumn( 'name', [ 'header' => __('Name'), 'type' => 'text', 'index' => 'name', 'header_css_class' => 'col-id', 'column_css_class' => 'col-id', ] ); $this->addColumn( 'email', [ 'header' => __('Email'), 'index' => 'email', 'class' => '', 'width' => '125px', ] ); $this->addColumn( 'created_at', [ 'header' => __('Created At'), 'index' => 'created_at', 'type' => 'datetime', ] ); $this->addColumn( 'action', [ 'header' => __('Action'), 'width' => '100px', 'type' => 'action', 'getter' => 'getId', 'actions' => [ [ 'caption' => __('Action Name'), 'url' => ['base' => 'routeName/controller/actionName'], 'field' => 'id' // pass id as parameter ] ], 'filter' => false, 'sortable' => false, 'index' => 'id', 'is_system' => true ] ); return parent::_prepareColumns(); } public function getGridUrl() { return $this->getUrl('*/*/actionName', ['_current' => true]); } } |
Create Admin Controller [Vendor]\[Module]\Controller\Adminhtml\Grid\Index.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
namespace [Vendor]\[Module]\Controller\Adminhtml\Grid; use Magento\Backend\App\Action; use Magento\Backend\App\Action\Context; use Magento\Framework\View\Result\PageFactory; class Index extends Action { protected $resultPageFactory; public function __construct( Context $context, PageFactory $resultPageFactory ) { parent::__construct($context); $this->resultPageFactory = $resultPageFactory; } public function execute() { $this->_view->loadLayout(); $resultPage = $this->resultPageFactory->create(); $resultPage->getConfig()->getTitle()->prepend(__('Grid Title')); $resultPage->setActiveMenu('Vendor_Module::gridList_name'); $resultPage->addBreadcrumb(__('Grid Name Process'), __('Grid Name List')); $this->_addContent($this->_view->getLayout()->createBlock('[Vendor]\[Module]\Block\Adminhtml\Grid\Grid')); $this->_view->renderLayout(); } protected function _isAllowed() { return true; } } |
Create [Vendor]/[Extension]/view/adminhtml/layout/route_controller_grid.xml
1 2 3 4 5 6 7 8 |
<?xml version="1.0"?> <page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd"> <body> <referenceContainer name="content"> <block class="[Vendor]\[Module]\Block\Adminhtml\Grid\Grid" name="grid_grid_listing"/> </referenceContainer> </body> </page> |
Method to Create Admin Grid in Magento 2 Using the UI_Component:
Create or add code in [Vendor]/[Extension]/etc/di.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<?xml version="1.0"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"> <virtualType name="Vendor]\[Module]\Model\ResourceModel\Extension\Grid\Collection" type="Magento\Framework\View\Element\UiComponent\DataProvider\SearchResult"> <arguments> <argument name="mainTable" xsi:type="string">mc_grid_data</argument> <argument name="resourceModel" xsi:type="string">Vendor\Extension\Model\ResourceModel\Extension</argument> </arguments> </virtualType> <type name="Magento\Framework\View\Element\UiComponent\DataProvider\CollectionFactory"> <arguments> <argument name="collections" xsi:type="array"> <item name="vendor_extension_grid_listing_data_source" xsi:type="string">Vendor\Extension\Model\ResourceModel\Extension\Grid\Collection</item> </argument> </arguments> </type> </config> |
Create xml [Vendor]/[Extension]/view/adminhtml/layout/route_controller_grid.xml
1 2 3 4 5 6 7 8 9 |
<?xml version="1.0"?> <page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd"> <update handle="styles"/> <body> <referenceContainer name="content"> <uiComponent name="route_controller_grid_list"/> </referenceContainer> </body> </page> |
Create xml for ui component grid listing [Vendor]/[Extension]/view/adminhtml/ui_component/route_controller_grid_list.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 |
<?xml version="1.0" encoding="UTF-8"?> <listing xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Ui/etc/ui_configuration.xsd"> <argument name="data" xsi:type="array"> <item name="js_config" xsi:type="array"> <item name="provider" xsi:type="string">somename_grid_list.somename_grid_data_source</item> <item name="deps" xsi:type="string">somename_grid_list.somename_grid_data_source</item> </item> <item name="spinner" xsi:type="string">somenames_columns</item> <item name="buttons" xsi:type="array"> <item name="add" xsi:type="array"> <item name="name" xsi:type="string">add</item> <item name="label" xsi:type="string" translate="true">Add</item> <item name="class" xsi:type="string">primary</item> <item name="url" xsi:type="string">route/container/addrow</item> </item> </item> </argument> <dataSource name="somename_grid_data_source"> <argument name="dataProvider" xsi:type="configurableObject"> <argument name="class" xsi:type="string"> Magento\Framework\View\Element\UiComponent\DataProvider\DataProvider </argument> <argument name="name" xsi:type="string">somename_grid_list_data_source</argument> <argument name="primaryFieldName" xsi:type="string">id</argument> <argument name="requestFieldName" xsi:type="string">id</argument> <argument name="data" xsi:type="array"> <item name="config" xsi:type="array"> <item name="update_url" xsi:type="url" path="mui/index/render"/> </item> </argument> </argument> <argument name="data" xsi:type="array"> <item name="js_config" xsi:type="array"> <item name="component" xsi:type="string">Magento_Ui/js/grid/provider</item> </item> </argument> </dataSource> <container name="listing_top"> <argument name="data" xsi:type="array"> <item name="config" xsi:type="array"> <item name="template" xsi:type="string">ui/grid/toolbar</item> <item name="stickyTmpl" xsi:type="string">ui/grid/sticky/toolbar</item> </item> </argument> <bookmark name="bookmarks"> <argument name="data" xsi:type="array"> <item name="config" xsi:type="array"> <item name="component" xsi:type="string">Magento_Ui/js/grid/controls/bookmarks/bookmarks</item> <item name="displayArea" xsi:type="string">dataGridActions</item> <item name="storageConfig" xsi:type="array"> <item name="saveUrl" xsi:type="url" path="mui/bookmark/save"/> <item name="deleteUrl" xsi:type="url" path="mui/bookmark/delete"/> <item name="namespace" xsi:type="string">somename_grid_list</item> </item> </item> </argument> </bookmark> <columnsControls name="columns_controls"/> <filterSearch name="fulltext"/> <filters name="listing_filters"> <argument name="data" xsi:type="array"> <item name="config" xsi:type="array"> <item name="storageConfig" xsi:type="array"> <item name="indexField" xsi:type="string">id</item> <item name="provider" xsi:type="string"> somename_grid_list.somename_grid_list.listing_top.bookmarks </item> <item name="namespace" xsi:type="string">current.filters</item> </item> <item name="childDefaults" xsi:type="array"> <item name="provider" xsi:type="string"> somename_grid_list.somename_grid_list.listing_top.listing_filters </item> <item name="imports" xsi:type="array"> <item name="visible" xsi:type="string"> somename_grid_list.somename_grid_list.somenames_columns.${ $.index }:visible </item> </item> </item> </item> </argument> </filters> <massaction name="listing_massaction"> <argument name="data" xsi:type="array"> <item name="config" xsi:type="array"> <item name="selectProvider" xsi:type="string"> somename_grid_list.somename_grid_list.somenames_columns.ids </item> <item name="component" xsi:type="string">Magento_Ui/js/grid/tree-massactions</item> <item name="indexField" xsi:type="string">id</item> </item> </argument> <action name="delete"> <argument name="data" xsi:type="array"> <item name="config" xsi:type="array"> <item name="type" xsi:type="string">delete</item> <item name="label" xsi:type="string" translate="true">Delete</item> <item name="url" xsi:type="url" path="route/controller/massdelete"/> <item name="confirm" xsi:type="array"> <item name="title" xsi:type="string" translate="true">Delete</item> <item name="message" xsi:type="string" translate="true">Do you want to delete selected row record? </item> </item> </item> </argument> </action> </massaction> <paging name="listing_paging"> <argument name="data" xsi:type="array"> <item name="config" xsi:type="array"> <item name="storageConfig" xsi:type="array"> <item name="provider" xsi:type="string"> somename_grid_list.somename_grid_list.listing_top.bookmarks </item> <item name="namespace" xsi:type="string">current.paging</item> </item> <item name="selectProvider" xsi:type="string"> somename_grid_list.somename_grid_list.somenames_columns.ids </item> </item> </argument> </paging> </container> <columns name="meetanshi_inquirys_columns"> <selectionsColumn name="ids"> <argument name="data" xsi:type="array"> <item name="config" xsi:type="array"> <item name="indexField" xsi:type="string">dealer_id</item> <item name="sorting" xsi:type="string">desc</item> <item name="sortOrder" xsi:type="number">10</item> </item> </argument> </selectionsColumn> <column name="id"> <argument name="data" xsi:type="array"> <item name="config" xsi:type="array"> <item name="filter" xsi:type="string">text</item> <item name="label" xsi:type="string" translate="true">ID</item> <item name="sortOrder" xsi:type="number">20</item> </item> </argument> </column> <column name="name"> <argument name="data" xsi:type="array"> <item name="config" xsi:type="array"> <item name="filter" xsi:type="string">text</item> <item name="label" xsi:type="string" translate="true">Name</item> <item name="sortOrder" xsi:type="number">30</item></item> </argument> </column> <actionsColumn name="actions" class="Vendor\Module\Ui\Component\Listing\Grid\Column\Actions"> <argument name="data" xsi:type="array"> <item name="config" xsi:type="array"> <item name="resizeEnabled" xsi:type="boolean">false</item> <item name="resizeDefaultWidth" xsi:type="string">107</item> <item name="indexField" xsi:type="string">id</item> </item> </argument> </actionsColumn> </columns> </listing> |
Create Controller [Vendor]\[Module]\Controller\Adminhtml\Dir_name
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
namespace Vendor\Module\Controller\Adminhtml\Dir_name; use Magento\Backend\App\Action; use Magento\Backend\App\Action\Context; use Magento\Framework\View\Result\PageFactory; class Index extends Action { protected $resultPageFactory; public function __construct( Context $context, PageFactory $resultPageFactory ) { parent::__construct($context); $this->resultPageFactory = $resultPageFactory; } public function execute() { $resultPage = $this->resultPageFactory->create(); $resultPage->setActiveMenu('Vendor_Module::grid_list'); // ui component grid name $resultPage->getConfig()->getTitle()->prepend((__('Manage Grid List'))); return $resultPage; } protected function _isAllowed() { return true; } } |
That’s it.Create a custom database table in Magento 2 to store and retrieve the data. Not only that, but you can also perform various operations such as insert, update and delete on the table data.
Follow any of the above methods and create Magento 2 admin grid to easily manage the database of the store!
Any doubts in the above methods are welcomed in the comments section below and I’d be happy to help 🙂
Please rate the post with 5 stars.
Sanjay Jethva
Sanjay is the co-founder and CTO of Meetanshi with hands-on expertise with Magento since 2011. He specializes in complex development, integrations, extensions, and customizations. Sanjay is one the top 50 contributor to the Magento community and is recognized by Adobe.
His passion for Magento 2 and Shopify solutions has made him a trusted source for businesses seeking to optimize their online stores. He loves sharing technical solutions related to Magento 2 & Shopify.
15 Comments
hello,
Can you explain the file structure and and flow in details of the admin grid..
Thank you,
Hello Nilesh,
You can follow the below blog for detailed explanation:
https://developer.adobe.com/commerce/php/development/components/add-admin-grid/
Thank You
May I know how to put grid into a custom gird?
Hello James,
We will post the solution in the future.
Do subscribe to Meetanshi’s blog posts to get notified for the same.
Thank You
meaning of Dir_name
Hello Anjana,
The dir_name contains the name that one has set in the controller folder.
For ex: app/code/Vendor/Module/Controller/Adminhtm/Grid/Index.php
Thank You
Hello,
Thanks for your post!
I’m trying to develop an extension with 2 different admin grids for 2 different tables.
How can I go with the di.xml to set 2 different source data, one for each table?
Hello,
You need to write code twice with a different name.
Thank you.
You switch from Vendor/Module to Vendor/Extension. Is this a typo or did you forget to explain a whole different part?
it’s just a typo, Marius. Thanks for catching that. I will update the code with the Vendor/Module ASAP.
In your Tag please add type=”Magento\Framework\View\Element\UiComponent\DataProvider\SearchResult”. As without it, it will not generate the class, and will give the error that the class not found.
Hey,
Thank you so much for drawing my attention.
I’ve updated the post.
Thank you. I understand that I can’t just copy and paste the code. I modified yours to my needs, but used what you had given to show an example of the error that was being thrown. I will look at your link. Clearly, I am missing the files that process the data and then send it to the grid. I am a beginner, so please forgive me if I don’t understand all of this yet. Just so you know, I have the module up and running, I am just missing the files to process the data.
I gave this a go, but when I created the 4 files you mention for the “Using the UI_Component” grid creation, I get an error directly related to the di.xml file. The classes in that file do not exist, specifically “Vendor\Extension\Model\ResourceModel\Extension\Grid\Collection” that file and class doesn’t exist. Even when I compile via command line, I get the error that the class does not exist. It seems there are other things required to create the grid, specifically to get the data to populate the grid. Can you share what they are?
You need to develop the custom module Vendor\extension and not directly paste the code.
For custom module development in Magento 2, you can take the reference from https://meetanshi.com/blog/magento-2-module-development/