Create UI Component Grid and Form in Magento 2

How to Create UI Component Grid and Form in Magento 2?

Today, we’re going to teach you guys how to create UI component grid and form in Magento 2.

UI component grid and form are two of the most important parts for admin in Magento 2.

UI component grid in Magento 2 offers many useful features for the admin users.

However, we’ve noticed that many Magento 2 developers face difficulties when trying to create UI component grid and form in the admin panel.

So, in this tutorial, we will show you how to create UI component grid and form in Magento 2. In addition, we will also show you how to perform CRUD operations such as save, delete, update, massStatus, massDelete records.

Steps to Create UI Component Grid and Form in Magento 2

Here is the step-by-step process to create UI component grid and form from scratch in Magento 2.

Step #1

Setup Folder

First of all, we will need to create an InstallSchema.php file in the app/code/MD/UiExample/Setup/ directory to create the database schema.

Next, copy the following code into the InstallSchema.php file.

<?php
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 *
 * Created By: MageDelight Pvt. Ltd.
 */
namespace Md\UiExample\Setup;
use Magento\Framework\DB\Ddl\Table;
use Magento\Framework\Setup\InstallSchemaInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\SchemaSetupInterface;
/**
 * @codeCoverageIgnore
 */
class InstallSchema implements InstallSchemaInterface
{
    /**
     * {@inheritdoc}
     * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
     */
    public function install(SchemaSetupInterface $setup, ModuleContextInterface $context)
    {
        $installer = $setup;
        $installer->startSetup();
        /**
         * Create table 'md_blog'
         */
        if (!$installer->tableExists('md_blog')) {
            $table = $installer->getConnection()->newTable(
                $installer->getTable('md_blog')
            )->addColumn(
                'id',
                Table::TYPE_INTEGER,
                null,
                [
                    'identity' => true,
                    'nullable' => false,
                    'primary' => true,
                    'unsigned' => true,
                ],
                'ID'
            )->addColumn(
                'name',
                Table::TYPE_TEXT,
                255,
                [
                    'nullable => false',
                ],
                'Name'
            )->addColumn(
                'title',
                Table::TYPE_TEXT,
                '255',
                [
                    'nullable => false',
                ],
                'Blog Title'
            )->addColumn(
                'content',
                Table::TYPE_TEXT,
                '2M',
                [],
                'Blog Content'
            )->addColumn(
                'status',
                Table::TYPE_SMALLINT,
                null,
                [
                    'nullable' => false,
                ],
                'Status'
            )->addColumn(
                'created_at',
                Table::TYPE_TIMESTAMP,
                null,
                [
                    'nullable' => false,
                    'default' => Table::TIMESTAMP_INIT,
                ],
                'Created At'
            )->setComment('Blog Table');
            $installer->getConnection()->createTable($table);
        }
        $installer->endSetup();
    }
}

Step #2

etc Folder

Now, the next step is to create a routes.xml file in the app/code/MD/UiExample/etc/adminhtml/ directory with the following code to set admin routes.

<?xml version="1.0"?>
<!--
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 * Created By: MageDelight Pvt. Ltd
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../lib/internal/Magento/Framework/App/etc/routes.xsd">
    <router id="admin">
        <route id="uiexample" frontName="uiexample">
            <module name="MD_UiExample" before="Magento_Adminhtml" />
        </route>
    </router>
</config>

Step #3

Next, we need to create a menu.xml file in the app/code/MD/UiExample/etc/adminhtml/ and add the following code to set the menu of our module.

<?xml version="1.0"?>
<!--
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 *
 * Created By: MageDelight Pvt. Ltd.
 */
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../Magento/Backend/etc/menu.xsd">
    <menu>
        <add id="MD_UiExample::view" title="MD Blog" module="MD_UiExample" sortOrder="50" resource="MD_UiExample::view"/>
        <add id="MD_UiExample::menu" title="Manage Grid" module="MD_UiExample" sortOrder="20" parent="MD_UiExample::view" action="uiexample/grid/index" resource="MD_UiExample::menu"/>
    </menu>
</config>

Step #4

Now, we also need to create a di.xml file in the app/code/MD/UiExample/etc/ directory with the following code to define some elements for our UI grid and form.

<?xml version="1.0"?>
<!--
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 *
 * Created By: MageDelight Pvt. Ltd.
 */
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/ObjectManager/etc/config.xsd">
    <!-- For Blog -->
    <virtualType name="MDUiExampleBlogFilterPool" type="Magento\Framework\View\Element\UiComponent\DataProvider\FilterPool">
        <arguments>
            <argument name="appliers" xsi:type="array">
                <item name="regular" xsi:type="object">Magento\Framework\View\Element\UiComponent\DataProvider\RegularFilter</item>
                <item name="fulltext" xsi:type="object">Magento\Framework\View\Element\UiComponent\DataProvider\FulltextFilter</item>
            </argument>
        </arguments>
    </virtualType>
    <virtualType name="MDUiExampleBlogFilterPool" type="Magento\Framework\View\Element\UiComponent\DataProvider\DataProvider">
        <arguments>
            <argument name="collection" xsi:type="object" shared="false">MD\UiExample\Model\ResourceModel\Blog\Collection</argument>
            <argument name="filterPool" xsi:type="object" shared="false">MDUiExampleBlogFilterPool</argument>
        </arguments>
    </virtualType>
    <type name="MD\UiExample\Model\ResourceModel\Blog\Grid\Collection">
        <arguments>
            <argument name="mainTable" xsi:type="string">md_blog</argument>
            <argument name="eventPrefix" xsi:type="string">md_uiexample_blog_grid_collection</argument>
            <argument name="eventObject" xsi:type="string">blog_grid_collection</argument>
            <argument name="resourceModel" xsi:type="string">MD\UiExample\Model\ResourceModel\Blog</argument>
        </arguments>
    </type>
    <type name="Magento\Framework\View\Element\UiComponent\DataProvider\CollectionFactory">
        <arguments>
            <argument name="collections" xsi:type="array">
                <item name="md_uiexample_blog_listing_data_source" xsi:type="string">MD\UiExample\Model\ResourceModel\Blog\Grid\Collection</item>
            </argument>
        </arguments>
    </type>
</config>

Step #5

Model Folder

After that, we will now create a Blog.php model file in the app/code/MD/UiExample/Model/ directory and copy the following code into the file.

<?php
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 *
 * Created By: MageDelight Pvt. Ltd
 */
namespace MD\UiExample\Model;
use Magento\Framework\Model\AbstractModel;
use MD\UiExample\Model\ResourceModel\Blog as BlogResourceModel;
class Blog extends \Magento\Framework\Model\AbstractModel
{
    protected function _construct()
    {
        $this->_init(BlogResourceModel::class);
    }
}

Step #6

Next, we will also need to create a Blog.php ResourceModel file in the app/code/MD/UiExample/Model/ResourceModel/ directory and copy the following code.

<?php
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 *
 * Created By: MageDelight Pvt. Ltd.
 */
namespace MD\UiExample\Model\ResourceModel;
use Magento\Framework\Model\ResourceModel\Db\AbstractDb;
class Blog extends AbstractDb
{
    /**
     * Initialize resource model
     *
     * @return void
     */
    protected function _construct()
    {
        $this->_init('md_blog', 'id');
    }
}

Step #7

After that, we will need to create a Collection.php file in the app/code/MD/UiExample/Model/ResourceModel/Blog/ and copy the following code.

<?php
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 *
 * Created By: MageDelight Pvt. Ltd
 */
namespace MD\UiExample\Model\ResourceModel\Blog;
use Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection;
use MD\UiExample\Model\Blog as BlogModel;
use MD\UiExample\Model\ResourceModel\Blog as BlogResourceModel;
class Collection extends AbstractCollection
{
    protected function _construct()
    {
        $this->_init(BlogModel::class, BlogResourceModel::class);
    }
}

Step #8

Now, we will also need to create a Collection.php grid collection file in the app/code/MD/UiExample/Model/ResourceModel/Blog/Grid/ and copy the following code.

<?php
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 *
 * Created By: MageDelight Pvt. Ltd.
 */
namespace MD\UiExample\Model\ResourceModel\Blog\Grid;
use Magento\Framework\View\Element\UiComponent\DataProvider\Document as BlogModel;
use MD\UiExample\Model\ResourceModel\Blog\Collection as BlogCollection;
class Collection extends BlogCollection implements \Magento\Framework\Api\Search\SearchResultInterface
{
    protected $aggregations;
    // @codingStandardsIgnoreStart
    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 = BlogModel::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);
    }
    // @codingStandardsIgnoreEnd
    public function getAggregations()
    {
        return $this->aggregations;
    }
    public function setAggregations($aggregations)
    {
        $this->aggregations = $aggregations;
    }
    public function getAllIds($limit = null, $offset = null)
    {
        return $this->getConnection()->fetchCol($this->_getAllIdsSelect($limit, $offset), $this->_bindParams);
    }
    public function getSearchCriteria()
    {
        return null;
    }
    public function setSearchCriteria(\Magento\Framework\Api\SearchCriteriaInterface $searchCriteria = null)
    {
        return $this;
    }
    public function getTotalCount()
    {
        return $this->getSize();
    }
    public function setTotalCount($totalCount)
    {
        return $this;
    }
    public function setItems(array $items = null)
    {
        return $this;
    }
}

Step #9

Now, the next step is to create a DataProvider.php file in the app/code/MD/UiExample/Model/ directory and copy the following code.

<?php
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 *
 * Created By: MageDelight Pvt. Ltd.
 */
namespace MD\UiExample\Model;
use MD\UiExample\Model\ResourceModel\Blog\CollectionFactory;
class DataProvider extends \Magento\Ui\DataProvider\AbstractDataProvider
{
    /**
     * @var array
     */
    protected $loadedData;
    // @codingStandardsIgnoreStart
    public function __construct(
        $name,
        $primaryFieldName,
        $requestFieldName,
        CollectionFactory $blogCollectionFactory,
        array $meta = [],
        array $data = []
    ) {
        $this->collection = $blogCollectionFactory->create();
        parent::__construct($name, $primaryFieldName, $requestFieldName, $meta, $data);
    }
    // @codingStandardsIgnoreEnd
    public function getData()
    {
        if (isset($this->loadedData)) {
            return $this->loadedData;
        }
        $items = $this->collection->getItems();
        foreach ($items as $blog) {
            $this->loadedData[$blog->getId()] = $blog->getData();
        }
        return $this->loadedData;
    }
}

Step #10

Controller Folder

After that, we will now create an Index.php file in the Controller Folder app/code/MD/UiExample/Controller/Adminhtml/Index/ directory and add the following code.

<?php
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 *
 * Created By: MageDelight Pvt. Ltd.
 */
namespace MD\UiExample\Controller\Adminhtml\Index;
class Index extends \Magento\Backend\App\Action
{
    /**
     * @var \Magento\Framework\View\Result\PageFactory
     */
    protected $resultPageFactory;
    /**
     * @param \Magento\Backend\App\Action\Context        $context
     * @param \Magento\Framework\View\Result\PageFactory $resultPageFactory
     */
    public function __construct(
        \Magento\Backend\App\Action\Context $context,
        \Magento\Framework\View\Result\PageFactory $resultPageFactory
    ) {
        parent::__construct($context);
        $this->resultPageFactory = $resultPageFactory;
    }
    /**
     * @return \Magento\Framework\View\Result\PageFactory
     */
    public function execute()
    {
        $resultPage = $this->resultPageFactory->create();
        $resultPage->getConfig()->getTitle()->prepend(__('Manage Grid'));
        return $resultPage;
    }
}

Step #11

After that, we also need to create an Add.php file in the app/code/MD/UiExample/Controller/Adminhtml/Index/ directory and copy the following code.

<?php
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 
 * Created By: MageDelight Pvt. Ltd.
 */
namespace MD\UiExample\Controller\Adminhtml\Index;
use Magento\Framework\Controller\ResultFactory;
class Add extends \Magento\Backend\App\Action
{
    /**
     * @return \Magento\Backend\Model\View\Result\Page
     */
    public function execute()
    {
        $resultPage = $this->resultPageFactory->create(ResultFactory::TYPE_PAGE);
        $resultPage->getConfig()->getTitle()->prepend(__('Add New Record'));
        return $resultPage;
    }
}

Step #12

Next, we will also need to create a Delete.php file in the app/code/MD/UiExample/Controller/Adminhtml/Index/ directory and add the following code.

<?php
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 *
 * Created By: MageDelight Pvt. Ltd.
 */
namespace MD\UiExample\Controller\Adminhtml\Index;
use Magento\Backend\App\Action;
class Delete extends Action
{
    /**
     * @var \MD\UiExample\Model\Blog
     */
    protected $modelBlog;
    /**
     * @param Context                  $context
     * @param \MD\UiExample\Model\Blog $blogFactory
     */
    public function __construct(
        Context $context,
        \MD\UiExample\Model\Blog $blogFactory
    ) {
        parent::__construct($context);
        $this->modelBlog = $model;
    }
    /**
     * {@inheritdoc}
     */
    protected function _isAllowed()
    {
        return $this->_authorization->isAllowed('MD_UiExample::index_delete');
    }
    /**
     * Delete action
     *
     * @return \Magento\Framework\Controller\ResultInterface
     */
    public function execute()
    {
        $id = $this->getRequest()->getParam('blog_id');
        /** @var \Magento\Backend\Model\View\Result\Redirect $resultRedirect */
        $resultRedirect = $this->resultRedirectFactory->create();
        if ($id) {
            try {
                $model = $this->modelBlog;
                $model->load($id);
                $model->delete();
                $this->messageManager->addSuccess(__('Record deleted successfully.'));
                return $resultRedirect->setPath('*/*/');
            } catch (\Exception $e) {
                $this->messageManager->addError($e->getMessage());
                return $resultRedirect->setPath('*/*/edit', ['id' => $id]);
            }
        }
        $this->messageManager->addError(__('Record does not exist.'));
        return $resultRedirect->setPath('*/*/');
    }
}

Step #13

Next, we need to create an Edit.php file in the app/code/MD/UiExample/Controller/Adminhtml/Index/ directory and copy the following code.

<?php
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 *
 * Created By: MageDelight Pvt. Ltd.
 */
namespace MD\UiExample\Controller\Adminhtml\Index;
use Magento\Framework\Controller\ResultFactory;
class Edit extends \Magento\Backend\App\Action {
    /**
     * @return \Magento\Backend\Model\View\Result\Page
     */
    public function execute() {
       $resultPage = $this->resultFactory->create(ResultFactory::TYPE_PAGE);
       $resultPage->getConfig()->getTitle()->prepend(__('Edit Record'));
       return $resultPage;
    }
}

Step #14

Then, we will also need to create a Save.php file in the app/code/MD/UiExample/Controller/Adminhtml/Index/ and add the following code.

<?php
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 *
 * Created By: MageDelight Pvt. Ltd.
 */
namespace MD\UiExample\Controller\Adminhtml\Index;
use Magento\Backend\App\Action;
use Magento\Backend\Model\Session;
use MD\UiExample\Model\Blog;
class Save extends \Magento\Backend\App\Action
{
    /*
     * @var Blog
     */
    protected $uiExamplemodel;
    /**
     * @var Session
     */
    protected $adminsession;
    /**
     * @param Action\Context $context
     * @param Blog           $uiExamplemodel
     * @param Session        $adminsession
     */
    public function __construct(
        Action\Context $context,
        Blog $uiExamplemodel,
        Session $adminsession
    ) {
        parent::__construct($context);
        $this->uiExamplemodel = $uiExamplemodel;
        $this->adminsession = $adminsession;
    }
    /**
     * Save blog record action
     *
     * @return \Magento\Backend\Model\View\Result\Redirect
     */
    public function execute()
    {
        $data = $this->getRequest()->getPostValue();
        $resultRedirect = $this->resultRedirectFactory->create();
        if ($data) {
            $blog_id = $this->getRequest()->getParam('blog_id');
            if ($blog_id) {
                $this->uiExamplemodel->load($blog_id);
            }
            $this->uiExamplemodel->setData($data);
            try {
                $this->uiExamplemodel->save();
                $this->messageManager->addSuccess(__('The data has been saved.'));
                $this->adminsession->setFormData(false);
                if ($this->getRequest()->getParam('back')) {
                    if ($this->getRequest()->getParam('back') == 'add') {
                        return $resultRedirect->setPath('*/*/add');
                    } else {
                        return $resultRedirect->setPath('*/*/edit', ['blog_id' => $this->uiExamplemodel->getBlogId(), '_current' => true]);
                    }
                }
                return $resultRedirect->setPath('*/*/');
            } catch (\Magento\Framework\Exception\LocalizedException $e) {
                $this->messageManager->addError($e->getMessage());
            } catch (\RuntimeException $e) {
                $this->messageManager->addError($e->getMessage());
            } catch (\Exception $e) {
                $this->messageManager->addException($e, __('Something went wrong while saving the data.'));
            }
            $this->_getSession()->setFormData($data);
            return $resultRedirect->setPath('*/*/edit', ['blog_id' => $this->getRequest()->getParam('blog_id')]);
        }
        return $resultRedirect->setPath('*/*/');
    }
}

Step #15

Next, we need to create a MassDelete.php file in the app/code/MD/UiExample/Controller/Adminhtml/Index/ and add the following code.

<?php
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 *
 * Created By: MageDelight Pvt. Ltd.
 */
namespace MD\UiExample\Controller\Adminhtml\Index;
use Magento\Backend\App\Action\Context;
use Magento\Framework\Controller\ResultFactory;
use Magento\Ui\Component\MassAction\Filter;
use MD\UiExample\Model\ResourceModel\Blog\CollectionFactory;
class MassDelete extends \Magento\Backend\App\Action
{
    /**
     * @var Filter
     */
    protected $filter;
    /**
     * @var CollectionFactory
     */
    protected $collectionFactory;
    /**
     * @param Context           $context
     * @param Filter            $filter
     * @param CollectionFactory $collectionFactory
     */
    public function __construct(
        Context $context,
        Filter $filter,
        CollectionFactory $collectionFactory
    ) {
        $this->filter = $filter;
        $this->collectionFactory = $collectionFactory;
        parent::__construct($context);
    }
    /**
     * Execute action
     *
     * @return \Magento\Backend\Model\View\Result\Redirect
     * @throws \Magento\Framework\Exception\LocalizedException|\Exception
     */
    public function execute()
    {
        $collection = $this->filter->getCollection($this->collectionFactory->create());
        $collectionSize = $collection->getSize();
        foreach ($collection as $item) {
            $item->delete();
        }
        $this->messageManager->addSuccess(__('A total of %1 element(s) have been deleted.', $collectionSize));
        /** @var \Magento\Backend\Model\View\Result\Redirect $resultRedirect */
        $resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT);
        return $resultRedirect->setPath('*/*/');
    }
}

Step #16

Lastly, in the Controller folder, we need to create a MassStatus.php file in the app/code/MD/UiExample/Controller/Adminhtml/Index/ directory and add the following code.

<?php
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 *
 * Created By: MageDelight Pvt. Ltd.
 */
namespace MD\UiExample\Controller\Adminhtml\Index;
use Magento\Backend\App\Action\Context;
use Magento\Framework\Controller\ResultFactory;
use Magento\Ui\Component\MassAction\Filter;
use MD\UiExample\Model\ResourceModel\Blog\CollectionFactory;
class MassStatus extends \Magento\Backend\App\Action
{
    /**
     * @var Filter
     */
    protected $filter;
    /**
     * @var CollectionFactory
     */
    protected $collectionFactory;
    /**
     * @param Context           $context
     * @param Filter            $filter
     * @param CollectionFactory $collectionFactory
     */
    public function __construct(
        Context $context,
        Filter $filter,
        CollectionFactory $collectionFactory
    ) {
        $this->filter = $filter;
        $this->collectionFactory = $collectionFactory;
        parent::__construct($context);
    }
    /**
     * Execute action
     *
     * @return \Magento\Backend\Model\View\Result\Redirect
     * @throws \Magento\Framework\Exception\LocalizedException|\Exception
     */
    public function execute()
    {
        $statusValue = $this->getRequest()->getParam('status');
        $collection = $this->filter->getCollection($this->collectionFactory->create());
        foreach ($collection as $item) {
          $item->setStatus($statusValue);
            $item->save();
        }
        $this->messageManager->addSuccess(__('A total of %1 record(s) have been modified.', $collection->getSize()));
        /** @var \Magento\Backend\Model\View\Result\Redirect $resultRedirect */
        $resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT);
        return $resultRedirect->setPath('*/*/');
    }
}

Step #17

Block Folder

In the Block folder, first we will need to create several files for buttons.

Let’s start with the Back.php button file in the app/code/MD/UiExample/Block/Adminhtml/Index/Edit/Button/ directory and copy the following code.

<?php
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 *
 * Created By: MageDelight Pvt. Ltd.
 */
namespace MD\UiExample\Block\Adminhtml\Index\Edit\Button;
use Magento\Framework\View\Element\UiComponent\Control\ButtonProviderInterface;
class Back extends Generic implements ButtonProviderInterface
{
    /**
     * Get button data
     *
     * @return array
     */
    public function getButtonData()
    {
        return [
            'label' => __('Back'),
            'on_click' => sprintf("location.href = '%s';", $this->getBackUrl()),
            'class' => 'back',
            'sort_order' => 10,
        ];
    }
    /**
     * Get URL for back (reset) button
     *
     * @return string
     */
    public function getBackUrl()
    {
        return $this->getUrl('*/*/');
    }
}

Step #18

After that, create a Delete.php file in the app/code/MD/UiExample/Block/Adminhtml/Index/Edit/Button/ directory and copy the following code.

<?php
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details
 *
 * Created By: MageDelight Pvt. Ltd.
 */
namespace MD\UiExample\Block\Adminhtml\Index\Edit\Button;
use Magento\Backend\Block\Widget\Context;
use Magento\Framework\View\Element\UiComponent\Control\ButtonProviderInterface;
class Delete extends Generic implements ButtonProviderInterface
{
    /**
     * @var Context
     */
    protected $context;
    /**
     * @param Context $context
     */
    public function __construct(
        Context $context
    ) {
        $this->context = $context;
    }
    /**
     * Get button data
     *
     * @return array
     */
    public function getButtonData()
    {
        $data = [];
        $blog_id = $this->context->getRequest()->getParam('blog_id');
        if ($blog_id) {
            $data = [
                'label' => __('Delete'),
                'class' => 'delete',
                'on_click' => 'deleteConfirm(\'' . __(
                    'Are you sure you want to do this?'
                ) . '\', \'' . $this->getDeleteUrl() . '\')',
                'sort_order' => 20,
            ];
        }
        return $data;
    }
    /**
     * @return string
     */
    public function getDeleteUrl()
    {
        $blog_id = $this->context->getRequest()->getParam('blog_id');
        return $this->getUrl('*/*/delete', ['blog_id' => $blog_id]);
    }
}

Step #19

Now, let’s create a Generic.php file in the app/code/MD/UiExample/Block/Adminhtml/Index/Edit/Button/ directory and copy the following code.

<?php
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 *
 * Created By: MageDelight Pvt. Ltd.
 */
namespace MD\UiExample\Block\Adminhtml\Index\Edit\Button;
use Magento\Backend\Block\Widget\Context;
/**
 * Class Generic
 */
class Generic
{
    /**
     * @var Context
     */
    protected $context;
    /**
     * @param Context $context
     */
    public function __construct(
        Context $context
    ) {
        $this->context = $context;
    }
    /**
     * Generate url by route and parameters
     *
     * @param string $route
     * @param array $params
     * @return string
     */
    public function getUrl($route = '', $params = [])
    {
        return $this->context->getUrlBuilder()->getUrl($route, $params);
    }
}

Step #20

After that, create a Reset.php file in the app/code/MD/UiExample/Block/Adminhtml/Index/Edit/Button/ directory and copy the following code.

<?php
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 *
 * Created By: MageDelight Pvt. Ltd.
 */
namespace MD\UiExample\Block\Adminhtml\Index\Edit\Button;
use Magento\Framework\View\Element\UiComponent\Control\ButtonProviderInterface;
class Reset implements ButtonProviderInterface
{
    /**
     * Get button data
     *
     * @return array
     */
    public function getButtonData()
    {
        return [
            'label' => __('Reset'),
            'class' => 'reset',
            'on_click' => 'location.reload();',
            'sort_order' => 30,
        ];
    }
}

Step #21

Lastly, also create a Save.php file in the app/code/MD/UiExample/Block/Adminhtml/Index/Edit/Button/ directory and copy the following code.

<?php
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 *
 * Created By: MageDelight Pvt. Ltd.
 */
namespace MD\UiExample\Block\Adminhtml\Index\Edit\Button;
use Magento\Framework\View\Element\UiComponent\Control\ButtonProviderInterface;
use Magento\Ui\Component\Control\Container;
class Save extends Generic implements ButtonProviderInterface
{
    /**
     * Get button data
     *
     * @return array
     */
    public function getButtonData()
    {
        return [
            'label' => __('Save'),
            'class' => 'save primary',
            'data_attribute' => [
                'mage-init' => [
                    'buttonAdapter' => [
                        'actions' => [
                            [
                                'targetName' => 'uiexample_form.uiexample_form',
                                'actionName' => 'save',
                                'params' => [false],
                            ],
                        ],
                    ],
                ],
            ],
            'class_name' => Container::SPLIT_BUTTON,
            'options' => $this->getOptions(),
        ];
    }
    /**
     * Retrieve options
     *
     * @return array
     */
    protected function getOptions()
    {
        $options[] = [
            'id_hard' => 'save_and_new',
            'label' => __('Save & New'),
            'data_attribute' => [
                'mage-init' => [
                    'buttonAdapter' => [
                        'actions' => [
                            [
                                'targetName' => 'uiexample_form.uiexample_form',
                                'actionName' => 'save',
                                'params' => [
                                    true, [
                                        'back' => 'add',
                                    ],
                                ],
                            ],
                        ],
                    ],
                ],
            ],
        ];
        $options[] = [
            'id_hard' => 'save_and_close',
            'label' => __('Save & Close'),
            'data_attribute' => [
                'mage-init' => [
                    'buttonAdapter' => [
                        'actions' => [
                            [
                                'targetName' => 'uiexample_form.uiexample_form',
                                'actionName' => 'save',
                                'params' => [true],
                            ],
                        ],
                    ],
                ],
            ],
        ];
        return $options;
    }
}

Step #22

UI Folder

In the UI folder, first we need to create various UI grid and action related files.

Let’s start with BlogActions.php file in the app/code/MD/UiExample/Ui/Component/Listing/Column/ directory with the following code to add our action buttons.

<?php
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 *
 * Created By: MageDelight Pvt. Ltd.
 */
namespace MD\UiExample\Ui\Component\Listing\Column;
class BlogActions extends \Magento\Ui\Component\Listing\Columns\Column
{
    const URL_EDIT_PATH = 'uiexample/index/edit';
    const URL_DELETE_PATH = 'uiexample/index/delete';
    /*
     * @var \Magento\Framework\UrlInterface
     */
    protected $urlBuilder;
    /**
     * @param \Magento\Framework\UrlInterface                              $urlBuilder
     * @param \Magento\Framework\View\Element\UiComponent\ContextInterface $context
     * @param \Magento\Framework\View\Element\UiComponentFactory           $uiComponentFactory
     * @param array                                                        $components
     * @param array                                                        $data
     */
    public function __construct(
        \Magento\Framework\UrlInterface $urlBuilder,
        \Magento\Framework\View\Element\UiComponent\ContextInterface $context,
        \Magento\Framework\View\Element\UiComponentFactory $uiComponentFactory,
        array $components = [],
        array $data = []
    ) {
        $this->urlBuilder = $urlBuilder;
        parent::__construct($context, $uiComponentFactory, $components, $data);
    }
    public function prepareDataSource(array $dataSource)
    {
        if (isset($dataSource['data']['items'])) {
            foreach ($dataSource['data']['items'] as &$item) {
                if (isset($item['blog_id'])) {
                    $item[$this->getData('name')] = [
                        'edit' => [
                            'href' => $this->urlBuilder->getUrl(
                                static::URL_EDIT_PATH,
                                [
                                    'blog_id' => $item['blog_id'
                                    ],
                                ]
                            ),
                            'label' => __('Edit'),
                        ],
                        'delete' => [
                            'href' => $this->urlBuilder->getUrl(
                                static::URL_DELETE_PATH,
                                [
                                    'blog_id' => $item['blog_id'
                                    ],
                                ]
                            ),
                            'label' => __('Delete'),
                        ],
                    ];
                }
            }
        }
        return $dataSource;
    }
}

Step #23

After that, we need to create an Options.php file in the app/code/MD/UiExample/Ui/Component/MassAction/Status/ directory with the following code to add status options.

<?php
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 *
 * Created By: MageDelight Pvt. Ltd.
 */
namespace MD\UiExample\Ui\Component\MassAction\Status;
use Magento\Framework\UrlInterface;
class Options extends \Magento\Ui\Component\Listing\Columns\Column
{
    /**
     * @var array
     */
    protected $options;
    /**
     * Additional options params
     *
     * @var array
     */
    protected $data;
    /**
     * @var UrlInterface
     */
    protected $urlBuilder;
    /**
     * Base URL for subactions
     *
     * @var string
     */
    protected $urlPath;
    /**
     * Param name for subactions
     *
     * @var string
     */
    protected $paramName;
    /**
     * Additional params for subactions
     *
     * @var array
     */
    protected $additionalData = [];
    /**
     * @param UrlInterface $urlBuilder
     * @param array        $data
     */
    public function __construct(
        UrlInterface $urlBuilder,
        array $data = []
    ) {
        $this->date = $data;
        $this->urlBuilder = $urlBuilder;
    }
    /**
     * Get action options
     *
     * @return array
     */
    public function jsonSerialize()
    {
        if ($this->options === null) {
            $options = [
                [
                    "value" => "1",
                    "label" => ('Active'),
                ],
                [
                    "value" => "0",
                    "label" => ('Inactive'),
                ],
            ];
            $this->prepareData();
            foreach ($options as $optionCode) {
                $this->options[$optionCode['value']] = [
                    'type' => 'status_' . $optionCode['value'],
                    'label' => $optionCode['label'],
                ];
                if ($this->urlPath && $this->paramName) {
                    $this->options[$optionCode['value']]['url'] = $this->urlBuilder->getUrl(
                        $this->urlPath,
                        [
                            $this->paramName => $optionCode['value'],
                        ]
                    );
                }
                $this->options[$optionCode['value']] = array_merge_recursive(
                    $this->options[$optionCode['value']],
                    $this->additionalData
                );
            }
            $this->options = array_values($this->options);
        }
        return $this->options;
    }
}

Step #24

Layout Folder

In the layout folder, we will be adding UI component grid and form in our demo project.

Let’s start by creating an uiexample_index_index.xml file in the app/code/MD/UiExample/view/adminhtml/layout/ directory with the following code to add UI grid in layout.

<?xml version="1.0"?/>
<!--
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 *
 * Created By: MageDelight Pvt. Ltd.
 */
-->
<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="md_uiexample_blog_listing"/>
        </referenceContainer>
    </body>
</page>

Step #25

After that, we also need to create an uiexample_index_add.xml file in the app/code/MD/UiExample/view/adminhtml/layout/ directory with the following code to add UI form in layout.

<?xml version="1.0"?>
<!--
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 *
 * Created By: MageDelight Pvt. Ltd.
 */
-->
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <update handle="styles"/>
    <body>
        <referenceContainer name="content">
            <uiComponent name="uiexample_form"/>
        </referenceContainer>
    </body>
</page>

Step #26

Lastly, we need to create an uiexample_index_edit.xml file in the app/code/MD/UiExample/view/adminhtml/layout/ directory with the following code to add UI form in layout.

<?xml version="1.0"?>
<!--
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 *
 * Created By: MageDelight Pvt. Ltd.
 */
-->
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <update handle="styles"/>
    <body>
        <referenceContainer name="content">
            <uiComponent name="uiexample_form"/>
        </referenceContainer>
    </body>
</page>

Step #27

ui_component folder

In the ui_component folder, we will finally create the UI Grid and Form file.

First of all, let’s create a md_uiexample_blog_listing.xml UI grid file at app/code/MD/UiExample/view/adminhtml/ui_component/ directory and copy the following code.

<?xml version="1.0" encoding="UTF-8"?>
<!--
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 *
 * Created By: MageDelight Pvt. Ltd.
 */
-->
<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">md_uiexample_blog_listing.md_uiexample_blog_listing_data_source</item>
         <item name="deps" xsi:type="string">md_uiexample_blog_listing.md_uiexample_blog_listing_data_source</item>
      </item>
      <item name="spinner" xsi:type="string">uiexample_blog_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 New</item>
            <item name="class" xsi:type="string">primary</item>
            <item name="url" xsi:type="string">*/*/add</item>
         </item>
      </item>
   </argument>
   <dataSource name="md_uiexample_blog_listing_data_source">
      <argument name="dataProvider" xsi:type="configurableObject">
         <argument name="class" xsi:type="string">MDUiExampleBlogFilterPool</argument>
         <argument name="name" xsi:type="string">md_uiexample_blog_listing_data_source</argument>
         <argument name="primaryFieldName" xsi:type="string">blog_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="cacheRequests" xsi:type="boolean">false</item>
               </item>
            </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="storageConfig" xsi:type="array">
                  <item name="namespace" xsi:type="string">md_uiexample_blog_listing</item>
               </item>
            </item>
         </argument>
      </bookmark>
      <component name="columns_controls">
         <argument name="data" xsi:type="array">
            <item name="config" xsi:type="array">
               <item name="columnsData" xsi:type="array">
                  <item name="provider" xsi:type="string">md_uiexample_blog_listing.md_uiexample_blog_listing.uiexample_blog_columns</item>
               </item>
               <item name="component" xsi:type="string">Magento_Ui/js/grid/controls/columns</item>
               <item name="displayArea" xsi:type="string">dataGridActions</item>
            </item>
         </argument>
      </component>
      <filterSearch name="fulltext">
         <argument name="data" xsi:type="array">
            <item name="config" xsi:type="array">
               <item name="provider" xsi:type="string">md_uiexample_blog_listing.md_uiexample_blog_listing_data_source</item>
               <item name="chipsProvider" xsi:type="string">md_uiexample_blog_listing.md_uiexample_blog_listing.listing_top.listing_filters_chips</item>
               <item name="storageConfig" xsi:type="array">
                  <item name="provider" xsi:type="string">md_uiexample_blog_listing.md_uiexample_blog_listing.listing_top.bookmarks</item>
                  <item name="namespace" xsi:type="string">current.search</item>
               </item>
            </item>
         </argument>
      </filterSearch>
      <filters name="listing_filters">
         <argument name="data" xsi:type="array">
            <item name="config" xsi:type="array">
               <item name="columnsProvider" xsi:type="string">md_uiexample_blog_listing.md_uiexample_blog_listing.uiexample_blog_columns</item>
               <item name="storageConfig" xsi:type="array">
                  <item name="provider" xsi:type="string">md_uiexample_blog_listing.md_uiexample_blog_listing.listing_top.bookmarks</item>
                  <item name="namespace" xsi:type="string">current.filters</item>
               </item>
               <item name="templates" xsi:type="array">
                  <item name="filters" xsi:type="array">
                     <item name="select" xsi:type="array">
                        <item name="component" xsi:type="string">Magento_Ui/js/form/element/ui-select</item>
                        <item name="template" xsi:type="string">ui/grid/filters/elements/ui-select</item>
                     </item>
                  </item>
               </item>
               <item name="childDefaults" xsi:type="array">
                  <item name="provider" xsi:type="string">md_uiexample_blog_listing.md_uiexample_blog_listing.listing_top.listing_filters</item>
                  <item name="imports" xsi:type="array">
                     <item name="visible" xsi:type="string">md_uiexample_blog_listing.md_uiexample_blog_listing.uiexample_blog_columns.${ $.index }:visible</item>
                  </item>
               </item>
            </item>
            <item name="observers" xsi:type="array">
               <item name="column" xsi:type="string">column</item>
            </item>
         </argument>
         <filterSelect name="store_id">
            <argument name="optionsProvider" xsi:type="configurableObject">
               <argument name="class" xsi:type="string">Magento\Cms\Ui\Component\Listing\Column\Cms\Options</argument>
            </argument>
            <argument name="data" xsi:type="array">
               <item name="config" xsi:type="array">
                  <item name="provider" xsi:type="string">${ $.parentName }</item>
                  <item name="imports" xsi:type="array">
                     <item name="visible" xsi:type="string">componentType = column, index = ${ $.index }:visible</item>
                  </item>
                  <item name="dataScope" xsi:type="string">store_id</item>
                  <item name="label" xsi:type="string" translate="true">Store View</item>
                  <item name="captionValue" xsi:type="string">0</item>
               </item>
            </argument>
         </filterSelect>
      </filters>
      <massaction name="listing_massaction">
         <argument name="data" xsi:type="array">
            <item name="config" xsi:type="array">
               <item name="selectProvider" xsi:type="string">md_uiexample_blog_listing.md_uiexample_blog_listing.uiexample_blog_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="is_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="uiexample/index/massDelete" />
                  <item name="confirm" xsi:type="array">
                     <item name="title" xsi:type="string" translate="true">Delete items</item>
                     <item name="message" xsi:type="string" translate="true">Are you sure you wan't to delete selected items?</item>
                  </item>
               </item>
            </argument>
         </action>
         <action name="change_status">
            <argument name="data" xsi:type="array">
               <item name="config" xsi:type="array">
                  <item name="type" xsi:type="string">change_status</item>
                  <item name="label" xsi:type="string" translate="true">Change status</item>
               </item>
            </argument>
            <argument name="actions" xsi:type="configurableObject">
               <argument name="class" xsi:type="string">MD\UiExample\Ui\Component\MassAction\Status\Options</argument>
               <argument name="data" xsi:type="array">
                  <item name="urlPath" xsi:type="string">*/*/massStatus</item>
                  <item name="paramName" xsi:type="string">status</item>
                  <item name="confirm" xsi:type="array">
                     <item name="title" xsi:type="string" translate="true">Update items status</item>
                     <item name="message" xsi:type="string" translate="true">Are you sure you wan't to update selected items status?</item>
                  </item>
               </argument>
            </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">md_uiexample_blog_listing.md_uiexample_blog_listing.listing_top.bookmarks</item>
                  <item name="namespace" xsi:type="string">current.paging</item>
               </item>
               <item name="selectProvider" xsi:type="string">md_uiexample_blog_listing.md_uiexample_blog_listing.uiexample_blog_columns.ids</item>
            </item>
         </argument>
      </paging>
   </container>
   <columns name="uiexample_blog_columns">
      <argument name="data" xsi:type="array">
         <item name="config" xsi:type="array">
            <item name="storageConfig" xsi:type="array">
               <item name="provider" xsi:type="string">md_uiexample_blog_listing.md_uiexample_blog_listing.listing_top.bookmarks</item>
               <item name="namespace" xsi:type="string">current</item>
            </item>
            <item name="childDefaults" xsi:type="array">
               <item name="fieldAction" xsi:type="array">
                  <item name="provider" xsi:type="string">md_uiexample_blog_listing.md_uiexample_blog_listing.uiexample_blog_columns</item>
                  <item name="target" xsi:type="string">startEdit</item>
                  <item name="params" xsi:type="array">
                     <item name="0" xsi:type="string">${ $.$data.rowIndex }</item>
                     <item name="1" xsi:type="boolean">true</item>
                  </item>
               </item>
               <item name="storageConfig" xsi:type="array">
                  <item name="provider" xsi:type="string">md_uiexample_blog_listing.md_uiexample_blog_listing.listing_top.bookmarks</item>
                  <item name="root" xsi:type="string">columns.${ $.index }</item>
                  <item name="namespace" xsi:type="string">current.${ $.storageConfig.root}</item>
               </item>
            </item>
         </item>
      </argument>
      <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">55</item>
               <item name="indexField" xsi:type="string">blog_id</item>
            </item>
            <item name="sortOrder" xsi:type="number">0</item>
         </argument>
      </selectionsColumn>
      <column name="blog_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 name="sortOrder" xsi:type="number">20</item>
            </item>
         </argument>
      </column>
      <column name="blog_title">
         <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">Blog Title</item>
               <item name="sortOrder" xsi:type="number">30</item>
            </item>
         </argument>
      </column>
      <column name="blog_description">
         <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">Blog Description</item>
               <item name="sortOrder" xsi:type="number">30</item>
            </item>
         </argument>
      </column>
      <column name="status">
         <argument name="data" xsi:type="array">
            <item name="options" xsi:type="array">
               <item name="0" xsi:type="array">
                  <item name="label" xsi:type="string">Active</item>
                  <item name="value" xsi:type="string">1</item>
               </item>
               <item name="1" xsi:type="array">
                  <item name="label" xsi:type="string">Inactive</item>
                  <item name="value" xsi:type="string">0</item>
               </item>
            </item>
            <item name="config" xsi:type="array">
               <item name="editor" xsi:type="string">select</item>
               <item name="filter" xsi:type="string">select</item>
               <item name="component" xsi:type="string">Magento_Ui/js/grid/columns/select</item>
               <item name="dataType" xsi:type="string">select</item>
               <item name="label" xsi:type="string" translate="true">Status</item>
            </item>
         </argument>
      </column>
      <actionsColumn name="actions" class="MD\UiExample\Ui\Component\Listing\Column\BlogActions">
         <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">blog_id</item>
               <item name="sortOrder" xsi:type="number">180</item>
            </item>
         </argument>
      </actionsColumn>
   </columns>
</listing>

Step #28

And lastly, we also need to create an uiexample_form.xml UI grid file in the app/code/MD/UiExample/view/adminhtml/ui_component/ directory and copy the following code.

<?xml version="1.0" encoding="UTF-8"?>
<!--
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 *
 * Created By: MageDelight Pvt. Ltd.
 */
-->
<form 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">uiexample_form.uiexample_form_data_source</item>
         <item name="deps" xsi:type="string">uiexample_form.uiexample_form_data_source</item>
      </item>
      <item name="label" xsi:type="string" translate="true">General Information</item>
      <item name="config" xsi:type="array">
         <item name="dataScope" xsi:type="string">data</item>
         <item name="namespace" xsi:type="string">uiexample_form</item>
      </item>
      <item name="spinner" xsi:type="string">general_information</item>
      <item name="buttons" xsi:type="array">
         <item name="back" xsi:type="string">MD\UiExample\Block\Adminhtml\Index\Edit\Button\Back</item>
         <item name="delete" xsi:type="string">MD\UiExample\Block\Adminhtml\Index\Edit\Button\Delete</item>
         <item name="reset" xsi:type="string">MD\UiExample\Block\Adminhtml\Index\Edit\Button\Reset</item>
         <item name="save" xsi:type="string">MD\UiExample\Block\Adminhtml\Index\Edit\Button\Save</item>
      </item>
      <item name="template" xsi:type="string">templates/form/collapsible</item>
   </argument>
   <dataSource name="uiexample_form_data_source">
      <argument name="dataProvider" xsi:type="configurableObject">
         <argument name="class" xsi:type="string">MD\UiExample\Model\DataProvider</argument>
         <argument name="name" xsi:type="string">uiexample_form_data_source</argument>
         <argument name="primaryFieldName" xsi:type="string">blog_id</argument>
         <argument name="requestFieldName" xsi:type="string">blog_id</argument>
         <argument name="data" xsi:type="array">
            <item name="config" xsi:type="array">
               <item name="submit_url" xsi:type="url" path="*/*/save" />
            </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/form/provider</item>
         </item>
      </argument>
   </dataSource>
   <fieldset name="general_information">
      <argument name="data" xsi:type="array">
         <item name="config" xsi:type="array">
            <item name="collapsible" xsi:type="boolean">false</item>
            <item name="label" xsi:type="string" translate="true">General Information</item>
            <item name="sortOrder" xsi:type="number">20</item>
         </item>
      </argument>
      <field name="status">
         <argument name="data" xsi:type="array">
            <item name="config" xsi:type="array">
               <item name="sortOrder" xsi:type="number">10</item>
               <item name="dataType" xsi:type="string">boolean</item>
               <item name="formElement" xsi:type="string">checkbox</item
               <item name="prefer" xsi:type="string">toggle</item>
               <item name="label" xsi:type="string" translate="true">Default Value</item>
               <item name="valueMap" xsi:type="array">
                  <item name="true" xsi:type="number">1</item>
                  <item name="false" xsi:type="number">0</item>
               </item>
               <item name="valuesForOptions" xsi:type="array">
                  <item name="boolean" xsi:type="string">boolean</item>
               </item>
               <item name="default" xsi:type="number">1</item>
               <item name="dataScope" xsi:type="string">status</item>
            </item>
         </argument>
      </field>
      <field name="blog_title">
         <argument name="data" xsi:type="array">
            <item name="config" xsi:type="array">
               <item name="dataType" xsi:type="string">text</item>
               <item name="label" xsi:type="string" translate="true">Blog Title</item>
               <item name="formElement" xsi:type="string">input</item>
               <item name="source" xsi:type="string">blog_title</item>
               <item name="dataScope" xsi:type="string">blog_title</item>
            </item>
         </argument>
      </field>
      <field name="blog_description">
         <argument name="data" xsi:type="array">
            <item name="config" xsi:type="array">
               <item name="dataType" xsi:type="string">text</item>
               <item name="label" xsi:type="string" translate="true">Blog Description</item>
               <item name="formElement" xsi:type="string">input</item>
               <item name="source" xsi:type="string">blog_description</item>
               <item name="dataScope" xsi:type="string">blog_description</item>
            </item>
         </argument>
      </field>
   </fieldset>
</form>

And it’s done!

Now, execute the following commands and check the output.

php bin/magento s:up
php bin/magento s:s:d -f
php bin/magento c:c

Conclusion

There you have it!

This is how you can create a UI component grid and form in Magento 2 and perform all sorts of CRUD operations.

We hope you found this tutorial helpful. If you have any queries, please share them in the comments below.

And if you need our professional assistance with Magento Development, feel free to reach out to us anytime.

Tags