🔥 Just Launched! Werra Premium Template for HyväSee it in Action

How to Create Admin Grid in Magento 2

By Sanjay JethvaUpdated on May 22, 2025 5 min read

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

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

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

<?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

<?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

<?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

<?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

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!


Sanjay Jethva Full Image
Article bySanjay 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.