Magento, Magento 2

Magento 2 : Create UI Component Grid and Form

Magento 2 Create UI Component Grid and Form

In this tutorial, Today I will explain you about how to create component UI grid and form in Magento 2. UI Component grid and form are most important part for admin in Magento 2.

Many developers face troubles when create UI grid and form in admin. UI Component grid provides many features and user friendly for admin users.

I will explain you here UI grid and form with CRUD operation like save, update, delete, massStatus, massDelete records. Let’s create step by step example. First of all, create module in your Magento store. Then, follow this below steps :

You may also like this :

Setup Folder

1) First of all, Create InstallSchema.php file for create database schema at app/code/RH/UiExample/Setup/ and paste the below code:

<?php
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 *
 * Created By : Rohan Hapani
 */
namespace RH\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 'rh_blog'
         */
        if (!$installer->tableExists('rh_blog')) {
            $table = $installer->getConnection()->newTable(
                $installer->getTable('rh_blog')
            )->addColumn(
                'blog_id',
                Table::TYPE_INTEGER,
                null,
                [
                    'identity' => true,
                    'nullable' => false,
                    'primary' => true,
                    'unsigned' => true,
                ],
                'Blog ID'
            )->addColumn(
                'blog_title',
                Table::TYPE_TEXT,
                255,
                [
                    'nullable => false',
                ],
                'Blog Title'
            )->addColumn(
                'blog_description',
                Table::TYPE_TEXT,
                '2M',
                [],
                'Blog Description'
            )->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();
    }
}

etc Folder

2) Then, Create routes.xml file for set admin routes at app/code/RH/UiExample/etc/adminhtml/ and paste the below code :

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

3) Then, Create menu.xml file for set menu of the module at app/code/RH/UiExample/etc/adminhtml/ and paste the below code :

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

4) After that, Create di.xml file for define some elements for ui grid and form at app/code/RH/UiExample/etc/ and paste the below code :

<?xml version="1.0"?>
<!--
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 *
 * Created By : Rohan Hapani
 */
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <!-- For Blog -->
    <virtualType name="RHUiExampleBlogFilterPool" 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="RHUiExampleBlogGridProvider" type="Magento\Framework\View\Element\UiComponent\DataProvider\DataProvider">
        <arguments>
            <argument name="collection" xsi:type="object" shared="false">RH\UiExample\Model\ResourceModel\Blog\Collection</argument>
            <argument name="filterPool" xsi:type="object" shared="false">RHUiExampleBlogFilterPool</argument>
        </arguments>
    </virtualType>
    <type name="RH\UiExample\Model\ResourceModel\Blog\Grid\Collection">
        <arguments>
            <argument name="mainTable" xsi:type="string">rh_blog</argument>
            <argument name="eventPrefix" xsi:type="string">rh_uiexample_blog_grid_collection</argument>
            <argument name="eventObject" xsi:type="string">blog_grid_collection</argument>
            <argument name="resourceModel" xsi:type="string">RH\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="rh_uiexample_blog_listing_data_source" xsi:type="string">RH\UiExample\Model\ResourceModel\Blog\Grid\Collection</item>
            </argument>
        </arguments>
    </type>
</config>

In addition, Let’s see short description of di.xml file :

First of all, we define provider class for applied filter in ui grid. This virtualType is connect with filter and searching.

<virtualType name="RHUiExampleBlogFilterPool" 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>

filerPool defines new element about filter collection and collection resolves to standard collection class

<virtualType name="RHUiExampleBlogFilterPool" type="Magento\Framework\View\Element\UiComponent\DataProvider\DataProvider">
    <arguments>
        <argument name="collection" xsi:type="object" shared="false">RH\UiExample\Model\ResourceModel\Blog\Collection</argument>
        <argument name="filterPool" xsi:type="object" shared="false">RHUiExampleBlogFilterPool</argument>
    </arguments>
</virtualType>

In addition, This below code will be configure our grid collection :

<type name="RH\UiExample\Model\ResourceModel\Blog\Grid\Collection">
    <arguments>
        <argument name="mainTable" xsi:type="string">rh_blog</argument>
        <argument name="eventPrefix" xsi:type="string">rh_uiexample_blog_grid_collection</argument>
        <argument name="eventObject" xsi:type="string">blog_grid_collection</argument>
        <argument name="resourceModel" xsi:type="string">RH\UiExample\Model\ResourceModel\Blog</argument>
    </arguments>
</type>

At the last, this will register our data source :

<type name="Magento\Framework\View\Element\UiComponent\DataProvider\CollectionFactory">
    <arguments>
        <argument name="collections" xsi:type="array">
            <item name="rh_uiexample_blog_listing_data_source" xsi:type="string">RH\UiExample\Model\ResourceModel\Blog\Grid\Collection</item>
        </argument>
    </arguments>
</type>

Model Folder

5) Now, we will create Blog.php model file at app/code/RH/UiExample/Model/ and paste the below code :

<?php
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 *
 * Created By : Rohan Hapani
 */
namespace RH\UiExample\Model;

use Magento\Framework\Model\AbstractModel;
use RH\UiExample\Model\ResourceModel\Blog as BlogResourceModel;

class Blog extends \Magento\Framework\Model\AbstractModel
{
    protected function _construct()
    {
        $this->_init(BlogResourceModel::class);
    }
}

6) Then, Create Blog.php ResourceModel file at app/code/RH/UiExample/Model/ResourceModel/ and paste the below code :

<?php
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 *
 * Created By : Rohan Hapani
 */
namespace RH\UiExample\Model\ResourceModel;

use Magento\Framework\Model\ResourceModel\Db\AbstractDb;

class Blog extends AbstractDb
{
    /**
     * Initialize resource model
     *
     * @return void
     */
    protected function _construct()
    {
        $this->_init('rh_blog', 'blog_id');
    }
}

7) Now, Create Collection.php file at app/code/RH/UiExample/Model/ResourceModel/Blog/ and paste the below code :

<?php
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 *
 * Created By : Rohan Hapani
 */
namespace RH\UiExample\Model\ResourceModel\Blog;

use Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection;
use RH\UiExample\Model\Blog as BlogModel;
use RH\UiExample\Model\ResourceModel\Blog as BlogResourceModel;

class Collection extends AbstractCollection
{
    protected function _construct()
    {
        $this->_init(BlogModel::class, BlogResourceModel::class);
    }
}

8) Then, Create Collection.php grid collection file at app/code/RH/UiExample/Model/ResourceModel/Blog/Grid/ and paste the below code :

<?php
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 *
 * Created By : Rohan Hapani
 */
namespace RH\UiExample\Model\ResourceModel\Blog\Grid;

use Magento\Framework\View\Element\UiComponent\DataProvider\Document as BlogModel;
use RH\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;
    }
}

9) After that, Create DataProvider.php dataprovider file at app/code/RH/UiExample/Model/ and paste the below code :

<?php
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 *
 * Created By : Rohan Hapani
 */
namespace RH\UiExample\Model;

use RH\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->getBlogId()] = $blog->getData();
        }
        return $this->loadedData;
    }
}

Controller Folder

10) In Controller folder, First of all, Create Index.php file at app/code/RH/UiExample/Controller/Adminhtml/Index/ and paste the below code :

<?php
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 *
 * Created By : Rohan Hapani
 */
namespace RH\UiExample\Controller\Adminhtml\Index;

use Magento\Framework\Controller\ResultFactory;

class Index extends \Magento\Backend\App\Action
{
    /**
     * @return \Magento\Framework\View\Result\PageFactory
     */
    public function execute()
    {

        $resultPage = $this->resultPageFactory->create(ResultFactory::TYPE_PAGE);
        $resultPage->getConfig()->getTitle()->prepend(__('Manage Grid'));
        return $resultPage;
    }
}

11) Then, Create Add.php  file at app/code/RH/UiExample/Controller/Adminhtml/Index/ and paste the below code :

<?php
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 *
 * Created By : Rohan Hapani
 */
namespace RH\UiExample\Controller\Adminhtml\Index;

use Magento\Framework\Controller\ResultFactory;

class Add extends \Magento\Backend\App\Action
{
    /**
     * @return \Magento\Framework\View\Result\PageFactory
     */
    public function execute()
    {
        $resultPage = $this->resultFactory->create(ResultFactory::TYPE_PAGE);
        $resultPage->getConfig()->getTitle()->prepend(__('Add New Record'));
        return $resultPage;
    }
}

12) Then, Create Delete.php controller file at app/code/RH/UiExample/Controller/Adminhtml/Index/ and paste the below code :

<?php
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 *
 * Created By : Rohan Hapani
 */
namespace RH\UiExample\Controller\Adminhtml\Index;

use Magento\Backend\App\Action;
use Magento\Backend\App\Action\Context;

class Delete extends Action
{

    /**
     * @var \RH\UiExample\Model\Blog
     */
    protected $rhblog;

    /**
     * @param Context $context
     * @param \RH\UiExample\Model\Blog $rhblog
     */
    public function __construct(
        Context $context,
        \RH\UiExample\Model\Blog $rhblog
    ) {
        parent::__construct($context);
        $this->rhblog = $rhblog;
    }

    /**
     * {@inheritdoc}
     */
    protected function _isAllowed()
    {
        return $this->_authorization->isAllowed('RH_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->rhblog;
                $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('*/*/');
    }
}

13) After that, Create Edit.php controller file at app/code/RH/UiExample/Controller/Adminhtml/Index/ and paste the below code :

<?php
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 *
 * Created By : Rohan Hapani
 */

namespace RH\UiExample\Controller\Adminhtml\Index;

use Magento\Framework\Controller\ResultFactory;

class Edit extends \Magento\Backend\App\Action
{
    /**
     * @return \Magento\Framework\Controller\ResultFactory
     */
    public function execute()
    {
        $resultPage = $this->resultFactory->create(ResultFactory::TYPE_PAGE);
        $resultPage->getConfig()->getTitle()->prepend(__('Edit Record'));
        return $resultPage;
    }
}

14) Then, Create Save.php controller file at app/code/RH/UiExample/Controller/Adminhtml/Index/ and paste the below code :

<?php
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 *
 * Created By : Rohan Hapani
 */
namespace RH\UiExample\Controller\Adminhtml\Index;

use Magento\Backend\App\Action;
use Magento\Backend\Model\Session;
use RH\UiExample\Model\Blog;

class Save extends \Magento\Backend\App\Action
{

    /**
     * @var Blog
     */
    protected $rhblog;

    /**
     * @var Session
     */
    protected $adminsession;

    /**
     * @param Action\Context $context
     * @param Blog $rhblog
     * @param Session $adminsession
     */
    public function __construct(
        Action\Context $context,
        Blog $rhblog,
        Session $adminsession
    ) {
        parent::__construct($context);
        $this->rhblog = $rhblog;
        $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->rhblog->load($blog_id);
            }

            $this->rhblog->setData($data);

            try {
                $this->rhblog->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->rhblog->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('*/*/');
    }
}

15) After, Create MassDelete.php controller file at app/code/RH/UiExample/Controller/Adminhtml/Index/ and paste the below code :

<?php
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 *
 * Created By : Rohan Hapani
 */
namespace RH\UiExample\Controller\Adminhtml\Index;

use Magento\Backend\App\Action\Context;
use Magento\Framework\Controller\ResultFactory;
use Magento\Ui\Component\MassAction\Filter;
use RH\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('*/*/');
    }
}

16) In this folder, Last create MassStatus.php controller file at app/code/RH/UiExample/Controller/Adminhtml/Index/ and paste the below code :

<?php
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 *
 * Created By : Rohan Hapani
 */
namespace RH\UiExample\Controller\Adminhtml\Index;

use Magento\Backend\App\Action\Context;
use Magento\Framework\Controller\ResultFactory;
use Magento\Ui\Component\MassAction\Filter;
use RH\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('*/*/');
    }
}

Block Folder

17) In this folder, First of all, we need to create files for buttons. Create Back.php file at app/code/RH/UiExample/Block/Adminhtml/Index/Edit/Button/ and paste the below code :

<?php
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 *
 * Created By : Rohan Hapani
 */
namespace RH\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('*/*/');
    }
}

18) Then, Create Delete.php file at app/code/RH/UiExample/Block/Adminhtml/Index/Edit/Button/ and paste the below code :

<?php
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 *
 * Created By : Rohan Hapani
 */
namespace RH\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]);
    }
}

19) After that, Create Generic.php file at app/code/RH/UiExample/Block/Adminhtml/Index/Edit/Button/ and paste the below code :

<?php
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 *
 * Created By : Rohan Hapani
 */
namespace RH\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);
    }
}

20) Then, Create Reset.php file at app/code/RH/UiExample/Block/Adminhtml/Index/Edit/Button/ and paste the below code :

<?php
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 *
 * Created By : Rohan Hapani
 */
namespace RH\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,
        ];
    }
}

21) In this folder, Last Create Save.php file at app/code/RH/UiExample/Block/Adminhtml/Index/Edit/Button/ and paste the below code :

<?php
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 *
 * Created By : Rohan Hapani
 */
namespace RH\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;
    }
}

Ui Folder

22) First of all, In this folder, we will create files for UI grid and action related files. Create BlogActions.php file for add action buttons at app/code/RH/UiExample/Ui/Component/Listing/Column/ and paste the below code :

<?php
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 *
 * Created By : Rohan Hapani
 */
namespace RH\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;
    }
}

23) Then, Create Options.php file for status options at app/code/RH/UiExample/Ui/Component/MassAction/Status/ and paste the below code :

<?php
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 *
 * Created By : Rohan Hapani
 */
namespace RH\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->data = $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;
    }
}

layout folder

24) In this folder, First of all, we will add UI component grid and form in layout. Create uiexample_index_index.xml file for add UI grid in layout at app/code/RH/UiExample/view/adminhtml/layout/ and paste the below code :

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

25) Then, Create uiexample_index_add.xml file for add UI form in layout at app/code/RH/UiExample/view/adminhtml/layout/ and paste the below code :

<?xml version="1.0"?>
<!--
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 *
 * Created By : Rohan Hapani
 */
-->
<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>

26) Then, Create uiexample_index_edit.xml file for add UI form in layout at app/code/RH/UiExample/view/adminhtml/layout/ and paste the below code :

<?xml version="1.0"?>
<!--
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 *
 * Created By : Rohan Hapani
 */
-->
<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>

ui_component folder

27) In this folder, First of all, we will create UI form and grid file. Create rh_uiexample_blog_listing.xml UI grid file at app/code/RH/UiExample/view/adminhtml/ui_component/ and paste the below code :

<?xml version="1.0" encoding="UTF-8"?>
<!--
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 *
 * Created By : Rohan Hapani
 */
-->
<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">rh_uiexample_blog_listing.rh_uiexample_blog_listing_data_source</item>
         <item name="deps" xsi:type="string">rh_uiexample_blog_listing.rh_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="rh_uiexample_blog_listing_data_source">
      <argument name="dataProvider" xsi:type="configurableObject">
         <argument name="class" xsi:type="string">RHUiExampleBlogGridProvider</argument>
         <argument name="name" xsi:type="string">rh_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">rh_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">rh_uiexample_blog_listing.rh_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">rh_uiexample_blog_listing.rh_uiexample_blog_listing_data_source</item>
               <item name="chipsProvider" xsi:type="string">rh_uiexample_blog_listing.rh_uiexample_blog_listing.listing_top.listing_filters_chips</item>
               <item name="storageConfig" xsi:type="array">
                  <item name="provider" xsi:type="string">rh_uiexample_blog_listing.rh_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">rh_uiexample_blog_listing.rh_uiexample_blog_listing.uiexample_blog_columns</item>
               <item name="storageConfig" xsi:type="array">
                  <item name="provider" xsi:type="string">rh_uiexample_blog_listing.rh_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">rh_uiexample_blog_listing.rh_uiexample_blog_listing.listing_top.listing_filters</item>
                  <item name="imports" xsi:type="array">
                     <item name="visible" xsi:type="string">rh_uiexample_blog_listing.rh_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">rh_uiexample_blog_listing.rh_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">blog_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">RH\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">rh_uiexample_blog_listing.rh_uiexample_blog_listing.listing_top.bookmarks</item>
                  <item name="namespace" xsi:type="string">current.paging</item>
               </item>
               <item name="selectProvider" xsi:type="string">rh_uiexample_blog_listing.rh_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">rh_uiexample_blog_listing.rh_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">rh_uiexample_blog_listing.rh_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">rh_uiexample_blog_listing.rh_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="RH\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>

28) At the last, Create uiexample_form.xml UI grid file at app/code/RH/UiExample/view/adminhtml/ui_component/ and paste the below code :

<?xml version="1.0" encoding="UTF-8"?>
<!--
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 *
 * Created By : Rohan Hapani
 */
-->
<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">RH\UiExample\Block\Adminhtml\Index\Edit\Button\Back</item>
         <item name="delete" xsi:type="string">RH\UiExample\Block\Adminhtml\Index\Edit\Button\Delete</item>
         <item name="reset" xsi:type="string">RH\UiExample\Block\Adminhtml\Index\Edit\Button\Reset</item>
         <item name="save" xsi:type="string">RH\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">RH\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">Status</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">textarea</item>
               <item name="source" xsi:type="string">blog_description</item>
               <item name="dataScope" xsi:type="string">blog_description</item>
            </item>
         </argument>
      </field>
   </fieldset>
</form>

Error Solution :

Class argument is invalid: RH\UiExample\Ui\Component\MassAction\Status\Options

1) Add this below code in your di.xml at app/code/RH/UiExample/etc/ file :

<type name="RH\UiExample\Ui\Component\MassAction\Status\Options">
    <arguments>
        <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" translatable="true">Change Status</item>
                <item name="message" xsi:type="string" translatable="true">Are you sure you wan't to update selected items status?</item>
            </item>
        </argument>
    </arguments>
</type>

2) Remove that below code from rh_uiexample_blog_listing.xml at app/code/RH/UiExample/view/adminhtml/ui_component

<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">RH\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>

3) And Replace that below code from rh_uiexample_blog_listing.xml at app/code/RH/UiExample/view/adminhtml/ui_component :

<action name="change_status">
    <settings>
        <type>change_status</type>
        <label translate="true">Change Status</label>
        <actions class="RH\UiExample\Ui\Component\MassAction\Status\Options"/>
    </settings>
</action>

If you will face above error then, solve using this below files update.

Now, just execute this below command to setup this module :

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

Finally, Your UI Grid and Form are ready !!! Cheers 🙂

I hope this blog will helpful for easily understand about how to create UI component grid and form in Magento 2. In case, I missed anything or need to add some information, always feel free to leave a comment in this blog, I’ll get back with proper solution 🙂

Tagged , , ,