Magento 2 – create an admin controller with menu items.

Magento 2 – create an admin controller with menu items.

thumbnail
Want to talk about your project?

In this topic, we will show you how to create a table in the database and manage it by creating a controller with a grid and menu item. In this case, we will create a blog with posts management.

Notice: Creating the module tutorial is here.

STEP 1. Create a controller file

First, you should create the controller file. In this example, there will be a controller with a blog index (grid). 

The file should have path like this pattern:

app/code/[your_namespace]/[your_module]/Controller/Adminhtml/[your_controller_name]/[your_controller_action].php

In our case it’s:

app/code/PandaGroup/MyAdminController/Controller/Adminhtml/Blog/Index.php

The code inside:

namespace PandaGroup\MyAdminController\Controller\Adminhtml\Blog;

use Magento\Backend\App\Action;
use Magento\Backend\App\Action\Context;
use Magento\Framework\View\Result\PageFactory;


/**
* Class Index
* @package PandaGroup\MyAdminController\Controller\Adminhtml\Blog
*/
class Index extends Action
  {
    protected $resultPageFactory = false;

    /**
     * Index constructor.
     * @param Context $context
     * @param PageFactory $resultPageFactory
     */
    public function __construct(
    Context $context,
    PageFactory $resultPageFactory
    ) {
    parent::__construct($context);
    $this->resultPageFactory = $resultPageFactory;
  }

    /**
     * @return \Magento\Framework\App\ResponseInterface|\Magento\Framework\Controller\ResultInterface|\Magento\Framework\View\Result\Page
     */
    public function execute()
  {
    $resultPage = $this->resultPageFactory->create();
    $resultPage->getConfig()->getTitle()->prepend((__('Blog')));

    return $resultPage;
  }
  }

STEP 2. Create routes.xml file

Secondly, you should create an XML file where you define name, id, and module name.

The file should be like this example path:

app/code/[your_namespace]/[your_module]/etc/adminhtml/routes.xml

In our case it’s:

app/code/PandaGroup/MyAdminController/etc/adminhtml/routes.xml

The code inside:

<?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="pandagroup_myadmincontroller
" frontName="pandagroup_myadmincontroller
">
           <module name="PandaGroup_MyAdminController"/>
       </route>
   </router>
</config>

Notice: Make sure that router id is admin. 

STEP 3. Create Model, Resource, Collection

You can check it here. 🙂

STEP 4. Create menu.xml

Now it’s time to create a menu item with a proper link to get on the blog index page with a grid. To do that we have to create a file with the path:

app/code/[your_namespace]/[your_module]/etc/adminhtml/menu.xml

In our case it’s:

app/code/PandaGroup/MyAdminController/etc/adminhtml/menu.xml

The code inside:

<?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="PandaGroup_MyAdminController::index" title="Blog" module="PandaGroup_MyAdminController" sortOrder="10" resource="PandaGroup_MyAdminController::index"/>
       <add id="PandaGroup_MyAdminController::blog" title="Manage Blog" module="PandaGroup_MyAdminController" sortOrder="20" action="pandagroup_myadmincontroller
/blog" resource="PandaGroup_MyAdminController::blog" parent="PandaGroup_MyAdminController::index"/>
   </menu>
</config>

STEP 5. Create Admin Grid Dependency Injection.

Firstly we need to create the dependency injection file (here you can declare what and where you want to inject – class etc.). In this case, we will connect our grid model with data (resource). The path of this file should be like:

app/code/[your_namespace]/[your_module]/etc/di.xml

In our case it’s:

app/code/PandaGroup/MyAdminController/etc/di.xml

Content of the file:

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/ObjectManager/etc/config.xsd">
   <type name="Magento\Framework\View\Element\UiComponent\DataProvider\CollectionFactory">
       <arguments>
           <argument name="collections" xsi:type="array">
               <item name="pandagroup_myadmincontroller_blog_listing_data_source" xsi:type="string">PandaGroup\MyAdminController\Model\ResourceModel\Blog\Grid\Collection</item>
           </argument>
       </arguments>
   </type>
   <virtualType name="PandaGroup\MyAdminController\Model\ResourceModel\Blog\Grid\Collection" type="Magento\Framework\View\Element\UiComponent\DataProvider\SearchResult">
       <arguments>
           <argument name="mainTable" xsi:type="string">pandagroup_myadmincontroller_blog</argument>
           <argument name="resourceModel" xsi:type="string">PandaGroup\MyAdminController\Model\ResourceModel\Blog</argument>
       </arguments>
   </virtualType>
</config>

STEP 6. Create Layout File.

In this file, you can declare what component should be used in the layout of the page. We have the action declared in menu.xml and routes.xml (front name) like pandagroup_myadmincontroller/blog/index, so we need to create a file named: pandagroup_myadmincontroller_blog_index.xml. The file path should be like:

app/code/[your_namespace]/[your_module]/view/adminhtml/layout/pandagroup_myadmincontroller_blog_index.xml

In our case it’s:

app/code/PandaGroup/MyAdminController/view/adminhtml/layout/pandagroup_myadmincontroller_blog_index.xml

Here we don’t want to change header or footer. We need to change the body – add components with a grid. So here is the content of the file:

<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="pandagroup_myadmincontroller_blog_listing"/>
       </referenceContainer>
   </body>
</page>

STEP 6. Create a UI Component File.

In this file, you can build your component. There are 2 basic types of components: listing and form. In this case, we will create a listing (grid).

The name of this file should be exactly the same as we declare in the layout file. So here will be pandagroup_myadmincontroller_blog_listing.xml.

The file path should be like:

app/code/[your_namespace]/[your_module]/view/adminhtml/layout/pandagroup_myadmincontroller_blog_index.xml

In our case it’s:

app/code/PandaGroup/MyAdminController/view/adminhtml/layout/pandagroup_myadmincontroller_blog_index.xml

<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">pandagroup_myadmincontroller_blog_listing.pandagroup_myadmincontroller_blog_listing_data_source
            </item>
            <item name="deps"
                  xsi:type="string">pandagroup_myadmincontroller_blog_listing.pandagroup_myadmincontroller_blog_listing_data_source
            </item>
        </item>
        <item name="spinner" xsi:type="string">spinner_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">New Post</item>
                <item name="class" xsi:type="string">primary</item>
                <item name="url" xsi:type="string">*/*/new</item>
            </item>
        </item>
    </argument>
    <dataSource name="nameOfDataSource">
        <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">pandagroup_myadmincontroller_blog_listing_data_source</argument>
            <argument name="primaryFieldName" xsi:type="string">post_id</argument>
            <argument name="requestFieldName" xsi:type="string">id</argument>
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="component" xsi:type="string">Magento_Ui/js/grid/provider</item>
                    <item name="update_url" xsi:type="url" path="mui/index/render"/>
                    <item name="storageConfig" xsi:type="array">
                        <item name="indexField" xsi:type="string">post_id</item>
                    </item>
                </item>
            </argument>
        </argument>
    </dataSource>
    <columns name="spinner_columns">
        <selectionsColumn name="ids">
            <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">70</item>
                    <item name="indexField" xsi:type="string">post_id</item>
                </item>
            </argument>
        </selectionsColumn>
        <column name="post_id">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="filter" xsi:type="string">textRange</item>
                    <item name="sorting" xsi:type="string">asc</item>
                    <item name="label" xsi:type="string" translate="true">Id</item>
                </item>
            </argument>
        </column>
        <column name="title">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="filter" xsi:type="string">text</item>
                    <item name="editor" xsi:type="array">
                        <item name="editorType" xsi:type="string">text</item>
                        <item name="validation" xsi:type="array">
                            <item name="required-entry" xsi:type="boolean">true</item>
                        </item>
                    </item>
                    <item name="label" xsi:type="string" translate="true">Title</item>
                </item>
            </argument>
        </column>
        <column name="slug">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="filter" xsi:type="string">text</item>
                    <item name="editor" xsi:type="array">
                        <item name="editorType" xsi:type="string">text</item>
                        <item name="validation" xsi:type="array">
                            <item name="required-entry" xsi:type="boolean">true</item>
                        </item>
                    </item>
                    <item name="label" xsi:type="string" translate="true">Slug</item>
                </item>
            </argument>
        </column>
        <column name="status">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="filter" xsi:type="string">text</item>
                    <item name="editor" xsi:type="array">
                        <item name="editorType" xsi:type="string">text</item>
                        <item name="validation" xsi:type="array">
                            <item name="required-entry" xsi:type="boolean">true</item>
                        </item>
                    </item>
                    <item name="label" xsi:type="string" translate="true">Status</item>
                </item>
            </argument>
        </column>
        <column name="created_at" className="Magento\Ui\Component\Listing\Columns\Date">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="filter" xsi:type="string">dateRange</item>
                    <item name="component" xsi:type="string">Magento_Ui/js/grid/columns/date</item>
                    <item name="dataType" xsi:type="string">date</item>
                    <item name="label" xsi:type="string" translate="true">Created At</item>
                </item>
            </argument>
        </column>
    </columns>
</listing>

So here we’ve added a “New Post” button (which doesn’t work now because there is no controller, layout, route, etc. for this page) columns with text & date. Here you can also declare filter & sorting type etc. More information about components you can find here:
https://devdocs.magento.com/guides/v2.4/ui_comp_guide/components/ui-listing-grid.html

And that’s it. Now you can clear & flush the cache and check if everything works.

...