Overview
To show how to add custom ui grid to the admin panel, we will use MageDirect_Faq module from this article.
Create ACL
Create Access Control List Rules (ACL) file to control access to our Faq grid:
PHP
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <!-- app/code/[VendorName]/[ModuleName]/etc/acl.xml --> <?xml version="1.0"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Acl/etc/acl.xsd"> <acl> <resources> <resource id="Magento_Backend::admin"> <resource id="Magento_Backend::content"> <resource id="Magento_Backend::content_elements"> <resource id="MageDirect_Faq::faq" title="Faqs" translate="title" sortOrder="100"/> </resource> </resource> </resource> </resources> </acl> </config> |
Add new menu item
Add new menu item by editing etc/adminhtml/menu.xml inside the module. In this case, we will add an item under Content > Elements:
PHP
1 2 3 4 5 6 7 8 9 | <!-- app/code/[VendorName]/[ModuleName]/etc/adminhtml/menu.xml --> <?xml version="1.0"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Backend:etc/menu.xsd"> <menu> <add id="MageDirect_Faq::faqs" title="Faqs" translate="title" module="MageDirect_Faq" sortOrder="100" parent="Magento_Backend::content_elements" action="faq/faq" resource="MageDirect_Faq::faq"/> </menu> </config> |
“Add” directive has next attributes:
- the id attribute is the unique name in format VendorName_ModuleName::menu_name;
- the title attribute will be visible in the menu bar;
- the module attribute specifies the module which this menu item belongs to;
- the action attribute contains the url of the page on which our admin grid will be shown;
- the resource attribute is used to define the ACL rule which the admin user must have in order to access this menu item;
- the parent attribute defines parent menu item;
- the sortOrder attribute defines menu item position inside menu bar.
Add routes.xml
- To etc/adminhtml folder add routes.xml file with the next content:
PHP
1 2 3 4 5 6 7 8 9 10 | <!-- app/code/[VendorName]/[ModuleName]/etc/adminhtml/routes.xml --> <?xml version="1.0"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd"> <router id="admin"> <route id="faq" frontName="faq"> <module name="MageDirect_Faq" /> </route> </router> </config> |
Create admin controller class
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 | <?php // app/code/[VendorName]/[ModuleName]/Controller/Adminhtml/Faq/Index.php namespace Magedirect\Faq\Controller\Adminhtml\Faq; use Magento\Backend\App\Action\Context; use Magento\Framework\View\Result\PageFactory; class Index extends \Magento\Backend\App\Action { /** * Authorization level of a basic admin session * * @see _isAllowed() */ const ADMIN_RESOURCE = 'MageDirect_Faq::faq'; /** * @var PageFactory */ protected $resultPageFactory; /** * @param Context $context * @param PageFactory $resultPageFactory */ public function __construct(Context $context, PageFactory $resultPageFactory) { $this->resultPageFactory = $resultPageFactory; parent::__construct($context); } /** * @return \Magento\Framework\Controller\ResultInterface */ public function execute() { /** @var \Magento\Backend\Model\View\Result\Page $resultPage */ $resultPage = $this->resultPageFactory->create(); $resultPage->setActiveMenu('MageDirect_Faq::faqs') ->getConfig()->getTitle()->prepend(__('Faqs')); return $resultPage; } } |
Clean cache
Clean cache and we will see the new empty page in the admin panel:
PHP
1 | <span style="font-weight: 400;">php bin/magento cache:clean</span> |
Now we can add a simple grid to this page by using UI Component. Let’s do it.
Сreate layout file
PHP
1 2 3 4 5 6 7 8 9 10 | <!-- app/code/[VendorName]/[ModuleName]/view/adminhtml/layout/faq_faq_index.xml --> <?xml version="1.0"?> <page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"> <body> <referenceContainer name="content"> <uiComponent name="faq_listing"/> </referenceContainer> </body> </page> |
Our UI Component will have a name faq_listing.
Create faq_listing.xml
Create faq_listing.xml inside ui_component folder:
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 | <!-- app/code/[VendorName]/[ModuleName]/view/adminhtml/ui_component/faq_listing.xml --> <?xml version="1.0" encoding="UTF-8"?> <listing xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd"> <argument name="data" xsi:type="array"> <item name="js_config" xsi:type="array"> <item name="provider" xsi:type="string">faq_listing.faq_listing_data_source</item> </item> </argument> <settings> <spinner>faq_listing_columns</spinner> <deps> <dep>faq_listing.faq_listing_data_source</dep> </deps> </settings> <dataSource name="faq_listing_data_source" component="Magento_Ui/js/grid/provider"> <settings> <storageConfig> <param name="indexField" xsi:type="string">faq_id</param> </storageConfig> <updateUrl path="mui/index/render"/> </settings> <aclResource>MageDirect_Faq::faq</aclResource> <dataProvider class="Magento\Framework\View\Element\UiComponent\DataProvider\DataProvider" name="faq_listing_data_source"> <settings> <requestFieldName>id</requestFieldName> <primaryFieldName>faq_id</primaryFieldName> </settings> </dataProvider> </dataSource> <columns name="faq_listing_columns"> <column name="faq_id"> <settings> <filter>textRange</filter> <label translate="true">ID</label> <sorting>asc</sorting> </settings> </column> <column name="title"> <settings> <filter>text</filter> <editor> <validation> <rule name="required-entry" xsi:type="boolean">true</rule> </validation> <editorType>text</editorType> </editor> <label translate="true">Title</label> </settings> </column> <column name="content"> <settings> <filter>text</filter> <editor> <validation> <rule name="required-entry" xsi:type="boolean">true</rule> </validation> <editorType>text</editorType> </editor> <label translate="true">Content</label> </settings> </column> <column name="created_at" class="Magento\Ui\Component\Listing\Columns\Date" component="Magento_Ui/js/grid/columns/date"> <settings> <filter>dateRange</filter> <dataType>date</dataType> <label translate="true">Created</label> </settings> </column> <column name="updated_at" class="Magento\Ui\Component\Listing\Columns\Date" component="Magento_Ui/js/grid/columns/date"> <settings> <filter>dateRange</filter> <dataType>date</dataType> <label translate="true">Modified</label> </settings> </column> </columns> </listing> |
Add the class
It is important to add the class that is responsible for preparing data for the grid (faq_listing_data_source):
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 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 | <!-- app/code/[VendorName]/[ModuleName]/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"> <type name="Magento\Framework\View\Element\UiComponent\DataProvider\CollectionFactory"> <arguments> <argument name="collections" xsi:type="array"> <item name="faq_listing_data_source" xsi:type="string">MageDirect\Faq\Model\ResourceModel\Faq\Grid\Collection</item> </argument> </arguments> </type> <type name="MageDirect\Faq\Model\ResourceModel\Faq\Grid\Collection"> <arguments> <argument name="mainTable" xsi:type="string">magedirect_faq</argument> <argument name="eventPrefix" xsi:type="string">magedirect_faq_grid_collection</argument> <argument name="eventObject" xsi:type="string">magedirect_faq_grid_collection</argument> <argument name="resourceModel" xsi:type="string">\MageDirect\Faq\Model\ResourceModel\Faq</argument> </arguments> </type> </config> <?php //app/code/[VendorName]/[ModuleName]/Model/ResourceModel/Faq/Grid/Collection.php namespace MageDirect\Faq\Model\ResourceModel\Faq\Grid; use Magento\Framework\Api\Search\SearchResultInterface; use Magento\Framework\Search\AggregationInterface; use MageDirect\Faq\Model\ResourceModel\Faq\Collection as FaqCollection; class Collection extends FaqCollection implements SearchResultInterface { /** * @var AggregationInterface */ protected $aggregations; /** * @param \Magento\Framework\Data\Collection\EntityFactoryInterface $entityFactory * @param \Psr\Log\LoggerInterface $logger * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy * @param \Magento\Framework\Event\ManagerInterface $eventManager * @param string $mainTable * @param string $eventPrefix * @param string $eventObject * @param string $resourceModel * @param string $model * @param \Magento\Framework\DB\Adapter\AdapterInterface|string|null $connection * @param \Magento\Framework\Model\ResourceModel\Db\AbstractDb $resource * * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( \Magento\Framework\Data\Collection\EntityFactoryInterface $entityFactory, \Psr\Log\LoggerInterface $logger, \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy, \Magento\Framework\Event\ManagerInterface $eventManager, $mainTable, $eventPrefix, $eventObject, $resourceModel, $model = \Magento\Framework\View\Element\UiComponent\DataProvider\Document::class, $connection = null, \Magento\Framework\Model\ResourceModel\Db\AbstractDb $resource = null ) { parent::__construct( $entityFactory, $logger, $fetchStrategy, $eventManager, $connection, $resource ); $this->_eventPrefix = $eventPrefix; $this->_eventObject = $eventObject; $this->_init($model, $resourceModel); $this->setMainTable($mainTable); } /** * @return AggregationInterface */ public function getAggregations() { return $this->aggregations; } /** * @param AggregationInterface $aggregations * @return $this */ public function setAggregations($aggregations) { $this->aggregations = $aggregations; } /** * Get search criteria. * * @return \Magento\Framework\Api\SearchCriteriaInterface|null */ public function getSearchCriteria() { return null; } /** * Set search criteria. * * @param \Magento\Framework\Api\SearchCriteriaInterface $searchCriteria * @return $this * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ public function setSearchCriteria(\Magento\Framework\Api\SearchCriteriaInterface $searchCriteria = null) { return $this; } /** * Get total count. * * @return int */ public function getTotalCount() { return $this->getSize(); } /** * Set total count. * * @param int $totalCount * @return $this * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ public function setTotalCount($totalCount) { return $this; } /** * Set items list. * * @param \Magento\Framework\Api\ExtensibleDataInterface[] $items * @return $this * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ public function setItems(array $items = null) { return $this; } } |
Clean cache and check the result:
Lilya GogolevaMagento Developer
Rate us
Please wait...
Related articles
- Follow this tutorial to clear Magento cache with no efforts. Also, you will...
- This easy and effortless tutorial on how to create the new admin account in...
- If you don’t know how to create a custom cache type in Magento, this article...
- SSL is very important for every online store as it initiates a secure session...
- The sitemap is highly important in case you want to optimize your website for...
- Want to manage email templates in your Magento 2 store? Check our article and...
- Do you know how to create custom product type? We know! And would be glad to...
- Want to have a Magento 2 Multistore? Read how our team setups...