:::: MENU ::::
Posts tagged with: magento 2

Magento 2 create basic module frontend part 4

As we finished with the basic module structure and admin part we move to Magento 2 create basic module frontend .Now this tutorial will be cover the create frontend router, create layout file, create frontend controller, create frontend block, add custom pagination. Now we start with frontend.

Create frontend router

Create routes.xml in following directory

QaisarSatti\HelloWorld\etc\frontend\

<?xml version="1.0"?>
<!--
/**
* Hello World
   *
   * @category    QaisarSatti
   * @package     QaisarSatti_HelloWorld
   * @author      Muhammad Qaisar Satti
   * @Email       [email protected]
   *
*/
-->
     <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd">
        <router id="standard">
            <route id="helloworld" frontName="helloworld">
                <module name="QaisarSatti_HelloWorld" />
            </route>
        </router>
    </config>

Create frontend controller

Create Index.php in following directory

QaisarSatti\HelloWorld\Controller\Index\

<?php
/**
 * Hello World
    *
    * @category    QaisarSatti
    * @package     QaisarSatti_HelloWorld
    * @author      Muhammad Qaisar Satti
    * @Email       [email protected]
    *
 */

namespace QaisarSatti\HelloWorld\Controller\Index;

class Index extends \Magento\Framework\App\Action\Action

{

    public function execute()
    {  
       
        $this->_view->loadLayout();
        $this->_view->renderLayout();
    }

}

Create layout file

Create helloworld_index_index.xml in following directory

QaisarSatti\HelloWorld\etc\frontend\

<?xml version="1.0"?>
<!--
/**
* Hello World
   *
   * @category    QaisarSatti
   * @package     QaisarSatti_HelloWorld
   * @author      Muhammad Qaisar Satti
   * @Email       [email protected]
   *
*/
-->
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
        <body>
            <referenceContainer name="content">
                <block class="QaisarSatti\HelloWorld\Block\HelloWorld" name="HellosWorld" template="QaisarSatti_HelloWorld::HelloWorld.phtml"></block>
            </referenceContainer>
        </body>
    </page>

Create frontend block

Create HelloWorld.php in following directory

QaisarSatti\HelloWorld\Block\

<?php
/**
 * Hello World
    *
    * @category    QaisarSatti
    * @package     QaisarSatti_HelloWorld
    * @author      Muhammad Qaisar Satti
    * @Email       [email protected]
    *
 */


namespace QaisarSatti\HelloWorld\Block;

class HelloWorld extends \Magento\Framework\View\Element\Template
{
      protected $_coreRegistry = null;
    protected $_collectionFactory;
    protected $_productsFactory;
    protected $_helloworldFactory;
   public function __construct(
        \Magento\Backend\Block\Template\Context $context,
        \Magento\Framework\Registry $registry,
        \QaisarSatti\HelloWorld\Model\ResourceModel\HelloWorld\CollectionFactory $helloworldFactory,
       array $data = []
   ) {
 
       $this->_coreRegistry = $registry;
       $this->_helloworldFactory = $helloworldFactory;
       parent::__construct($context, $data);
   }
   public function getHelloCollection()
        {
          $page=($this->getRequest()->getParam('p'))? $this->getRequest()->getParam('p') : 1;
           //get values of current limit
          $pageSize=($this->getRequest()->getParam('limit'))? $this->getRequest()->getParam('limit') : 5;

          $helloCollection = $this->_helloworldFactory->create();
          $helloCollection->setPageSize($pageSize);
          $helloCollection->setCurPage($page);
          return $helloCollection;
        }
   public function _prepareLayout()
   {
   
       parent::_prepareLayout();
       $this->pageConfig->getTitle()->set(__('Sample Post'));

       if ($this->getHelloCollection()) {
            $pager = $this->getLayout()->createBlock('Magento\Theme\Block\Html\Pager','qaisarsatti.blog.pager')->setAvailableLimit(array(5=>5,10=>10,15=>15,20=>20));
            $pager->setShowPerPage(true);
            $pager->setCollection($this->getHelloCollection());
            $this->setChild('pager', $pager);
            $this->getHelloCollection()->load();
        }
        return $this;
   }
   public function getPagerHtml(){
        return $this->getChildHtml('pager');
    }


}

Create frontend phtml

Create HelloWorld.phtml in following directory

QaisarSatti\HelloWorld\view\frontend\templates\

<?php
/**
 * Hello World
    *
    * @category    QaisarSatti
    * @package     QaisarSatti_HelloWorld
    * @author      Muhammad Qaisar Satti
    * @Email       [email protected]
    *
 */

$blogCollection = $block->getHelloCollection();
foreach ($blogCollection as $blog) {

    echo $blog->getTitle().'<br />';
    echo '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'.$blog->getContent().'<br />';
}

 if ($block->getPagerHtml()): ?>
<div class="order-products-toolbar toolbar bottom">
<?php echo $block->getPagerHtml(); ?>
</div>
<?php endif ?>
Author: Qaisar Satti
Category: Magento 2
Last Modified: February 9, 2018


Magento 2 create basic module admin form part 3

As we completed the admin grid part now we move to part Magento 2 create basic module admin form. In this tutorial include admin new ui component form , admin edit ui component form , form data provider,edit form delete button and add different button to form. Now move on creating the ui component form.

Add New Form controller

Now we create controller for adding the new record. This controller just forwarding to edit controller. Create controller for NewAction.php in following directory

QaisarSatti\HelloWorld\Controller\Adminhtml\Index\

<?php
/**
 * Hello World
    *
    * @category    QaisarSatti
    * @package     QaisarSatti_HelloWorld
    * @author      Muhammad Qaisar Satti
    * @Email       [email protected]
    *
 */

namespace QaisarSatti\HelloWorld\Controller\Adminhtml\Index;

class NewAction extends \Magento\Backend\App\Action
{
    /**
     * @var \Magento\Backend\Model\View\Result\Forward
     */

    protected $resultForwardFactory;

    /**
     * @param \Magento\Backend\App\Action\Context $context
     * @param \Magento\Backend\Model\View\Result\ForwardFactory $resultForwardFactory
     */

    public function __construct(
        \Magento\Backend\App\Action\Context $context,
        \Magento\Backend\Model\View\Result\ForwardFactory $resultForwardFactory
    ) {
        $this->resultForwardFactory = $resultForwardFactory;
        parent::__construct($context);
    }

    /**
     * {@inheritdoc}
     */

    protected function _isAllowed()
    {
        return $this->_authorization->isAllowed('QaisarSatti_HelloWorld::helloworld1');
    }

    /**
     * Forward to edit
     *
     * @return \Magento\Backend\Model\View\Result\Forward
     */

    public function execute()
    {
        /** @var \Magento\Backend\Model\View\Result\Forward $resultForward */
        $resultForward = $this->resultForwardFactory->create();
        return $resultForward->forward('edit');
    }
}

Edit Form

Edit form is based on three parts edit controller, edit layout, and edit ui component. So we go through one by one.

Edit Form controller

Now we create controller for adding the new record. This controller just forwarding to edit controller. Create controller for Edit.php in following directory

QaisarSatti\HelloWorld\Controller\Adminhtml\Index\

<?php
/**
 * Hello World
    *
    * @category    QaisarSatti
    * @package     QaisarSatti_HelloWorld
    * @author      Muhammad Qaisar Satti
    * @Email       [email protected]
    *
 */

namespace QaisarSatti\HelloWorld\Controller\Adminhtml\Index;

class Edit extends \Magento\Backend\App\Action
{
    /**
     * @var \Magento\Framework\View\Result\PageFactory
     */

    protected $resultPageFactory;

    /**
     * @param \Magento\Backend\App\Action\Context $context
     * @param \Magento\Framework\Registry $coreRegistry
     * @param \Magento\Framework\View\Result\PageFactory $resultPageFactory
     */

    public function __construct(
        \Magento\Backend\App\Action\Context $context,
        \Magento\Framework\Registry $coreRegistry,
        \Magento\Framework\View\Result\PageFactory $resultPageFactory
    ) {
        $this->resultPageFactory = $resultPageFactory;
        parent::__construct($context, $coreRegistry);
    }

    /**
     * Index action
     *
     * @return \Magento\Framework\Controller\ResultInterface
     */

    public function execute()
    {

        $resultPage = $this->resultPageFactory->create();
        $this->initPage($resultPage)->getConfig()->getTitle()->prepend(__('Manage Post'));
        return $resultPage;
    }
    protected function initPage($resultPage)
    {
         $resultPage->setActiveMenu('QaisarSatti_HelloWorld::helloworld1')
             ->addBreadcrumb(__('Manage Post'), __('Manage Post'))
             ->addBreadcrumb(__('Manage Post'), __('Manage Post'));

         return $resultPage;
    }

    /**
     * Check the permission to run it
     *
     * @return boolean
     */

    protected function _isAllowed()
    {
        return $this->_authorization->isAllowed('QaisarSatti_HelloWorld::helloworld1');
    }
}

Edit Form layout

Now we create layout file for edit. This helloworld_index_edit.xml file combine the ui component with edit controller. Create controller for helloworld_index_edit.xml in following directory

QaisarSatti\HelloWorld\view\adminhtml\layout\

<?xml version="1.0"?>
<!--
   /**
   * Hello World
   *
   * @category    QaisarSatti
   * @package     QaisarSatti_HelloWorld
   * @author      Muhammad Qaisar Satti
   * @Email       [email protected]
   *
*/
-->
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <body>
        <referenceContainer name="content">
            <uiComponent name="helloworld_edit"/>
        </referenceContainer>
     
    </body>
</page>

Data Provider for Edit Form

Now create the data provider for admin form. Create DataProvider.php in following directory

QaisarSatti\HelloWorld\Model\HelloWorld\

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

namespace QaisarSatti\HelloWorld\Model\HelloWorld;

use QaisarSatti\HelloWorld\Model\ResourceModel\HelloWorld\CollectionFactory;
use Magento\Framework\App\Request\DataPersistorInterface;

/**
 * Class DataProvider
 */

class DataProvider extends \Magento\Ui\DataProvider\AbstractDataProvider
{
    /**
     * @var \Magento\Cms\Model\ResourceModel\Block\Collection
     */

    protected $collection;

    /**
     * @var DataPersistorInterface
     */

    protected $dataPersistor;

    /**
     * @var array
     */

    protected $loadedData;

    /**
     * Constructor
     *
     * @param string $name
     * @param string $primaryFieldName
     * @param string $requestFieldName
     * @param CollectionFactory $blockCollectionFactory
     * @param DataPersistorInterface $dataPersistor
     * @param array $meta
     * @param array $data
     */

    public function __construct(
        $name,
        $primaryFieldName,
        $requestFieldName,
        CollectionFactory $helloworldCollectionFactory,
        DataPersistorInterface $dataPersistor,
        array $meta = [],
        array $data = []
    ) {
        $this->collection = $helloworldCollectionFactory->create();
        $this->dataPersistor = $dataPersistor;
        parent::__construct($name, $primaryFieldName, $requestFieldName, $meta, $data);
    }

    /**
     * Get data
     *
     * @return array
     */

    public function getData()
    {
        if (isset($this->loadedData)) {
            return $this->loadedData;
        }
        $items = $this->collection->getItems();
        /** @var \Magento\Cms\Model\Block $block */
        foreach ($items as $block) {
            $this->loadedData[$block->getId()] = $block->getData();
        }

        $data = $this->dataPersistor->get('helloworld');
        if (!empty($data)) {
            $block = $this->collection->getNewEmptyItem();
            $block->setData($data);
            $this->loadedData[$block->getId()] = $block->getData();
            $this->dataPersistor->clear('helloworld');
        }

        return $this->loadedData;
    }
}

Edit Form Generic Button

Create GenericButton.php in following directory

QaisarSatti\HelloWorld\Block\Adminhtml\HelloWorld\Edit\

<?php
/**
 * Hello World
    *
    * @category    QaisarSatti
    * @package     QaisarSatti_HelloWorld
    * @author      Muhammad Qaisar Satti
    * @Email       [email protected]
    *
 */

namespace QaisarSatti\HelloWorld\Block\Adminhtml\HelloWorld\Edit;

use Magento\Backend\Block\Widget\Context;
use Magento\Framework\Exception\NoSuchEntityException;

/**
 * Class GenericButton
 */

class GenericButton
{
    /**
     * @var Context
     */

    protected $context;

    /**
     * @var BlockRepositoryInterface
     */


    /**
     * @param Context $context
     */

    public function __construct(
        Context $context
    ) {
        $this->context = $context;
    }

    /**
     * Return Post ID
     *
     * @return int|null
     */

    public function getBlockId()
    {
        try {
            return $this->context->getRequest()->getParam('post_id');

        } catch (NoSuchEntityException $e) {
        }
        return null;
    }

    /**
     * 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);
    }
}

Edit Form Back Button

Create BackButton.php in following directory

QaisarSatti\HelloWorld\Block\Adminhtml\HelloWorld\Edit\

<?php
/**
 * Hello World
    *
    * @category    QaisarSatti
    * @package     QaisarSatti_HelloWorld
    * @author      Muhammad Qaisar Satti
    * @Email       [email protected]
    *
 */

namespace QaisarSatti\HelloWorld\Block\Adminhtml\HelloWorld\Edit;

use Magento\Framework\View\Element\UiComponent\Control\ButtonProviderInterface;

/**
 * Class BackButton
 */

class BackButton extends GenericButton implements ButtonProviderInterface
{
    /**
     * @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('*/*/');
    }
}

Edit Form Delete Button

Create DeleteButton.php in following directory

QaisarSatti\HelloWorld\Block\Adminhtml\HelloWorld\Edit\

<?php
/**
 * Hello World
    *
    * @category    QaisarSatti
    * @package     QaisarSatti_HelloWorld
    * @author      Muhammad Qaisar Satti
    * @Email       [email protected]
    *
 */

namespace QaisarSatti\HelloWorld\Block\Adminhtml\HelloWorld\Edit;

use Magento\Framework\View\Element\UiComponent\Control\ButtonProviderInterface;

/**
 * Class DeleteButton
 */

class DeleteButton extends GenericButton implements ButtonProviderInterface
{

    /**
     * @return array
     */

    public function getButtonData()
    {
        $data = [];
        return $data;
        if ($this->getId()) {
            $data = [
                'label' => __('Delete Block'),
                '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()
    {
        return $this->getUrl('*/*/delete', ['id' => $this->getId()]);
    }
}

Edit Form Reset Button

Create ResetButton.php in following directory

QaisarSatti\HelloWorld\Block\Adminhtml\HelloWorld\Edit\

<?php
/**
 * Hello World
    *
    * @category    QaisarSatti
    * @package     QaisarSatti_HelloWorld
    * @author      Muhammad Qaisar Satti
    * @Email       [email protected]
    *
 */

namespace QaisarSatti\HelloWorld\Block\Adminhtml\HelloWorld\Edit;

use Magento\Framework\View\Element\UiComponent\Control\ButtonProviderInterface;

/**
 * Class ResetButton
 */

class ResetButton implements ButtonProviderInterface
{
    /**
     * @return array
     */

    public function getButtonData()
    {
        return [
            'label' => __('Reset'),
            'class' => 'reset',
            'on_click' => 'location.reload();',
            'sort_order' => 30
        ];
    }
}

Edit Form SaveAndContinue Button

Create SaveAndContinueButton.php in following directory

QaisarSatti\HelloWorld\Block\Adminhtml\HelloWorld\Edit\

<?php
/**
 * Hello World
    *
    * @category    QaisarSatti
    * @package     QaisarSatti_HelloWorld
    * @author      Muhammad Qaisar Satti
    * @Email       [email protected]
    *
 */

namespace QaisarSatti\HelloWorld\Block\Adminhtml\HelloWorld\Edit;

use Magento\Framework\View\Element\UiComponent\Control\ButtonProviderInterface;

/**
 * Class SaveAndContinueButton
 */

class SaveAndContinueButton extends GenericButton implements ButtonProviderInterface
{

    /**
     * @return array
     */

    public function getButtonData()
    {
        return [
            'label' => __('Save and Continue Edit'),
            'class' => 'save',
            'data_attribute' => [
                'mage-init' => [
                    'button' => ['event' => 'saveAndContinueEdit'],
                ],
            ],
            'sort_order' => 80,
        ];
    }
}

Edit Form Save Button

Create SaveButton.php in following directory

QaisarSatti\HelloWorld\Block\Adminhtml\HelloWorld\Edit\

<?php
/**
 * Hello World
    *
    * @category    QaisarSatti
    * @package     QaisarSatti_HelloWorld
    * @author      Muhammad Qaisar Satti
    * @Email       [email protected]
    *
 */

namespace QaisarSatti\HelloWorld\Block\Adminhtml\HelloWorld\Edit;

use Magento\Framework\View\Element\UiComponent\Control\ButtonProviderInterface;

/**
 * Class SaveButton
 * @package Magento\Customer\Block\Adminhtml\Edit
 */

class SaveButton extends GenericButton implements ButtonProviderInterface
{
    /**
     * @return array
     */

    public function getButtonData()
    {
        return [
            'label' => __('Save Post'),
            'class' => 'save primary',
            'data_attribute' => [
                'mage-init' => ['button' => ['event' => 'save']],
                'form-role' => 'save',
            ],
            'sort_order' => 90,
        ];
    }
}

Edit Form UI Component

Now create the ui component for the grid. You can read detail of edit form from tutorial Magento 2 create custom ui component admin form. Now we Create helloworld_edit.xml in following directory

QaisarSatti\HelloWorld\view\adminhtml\ui_component\

<?xml version="1.0" encoding="UTF-8"?>
<!--
/**
* Hello World
   *
   * @category    QaisarSatti
   * @package     QaisarSatti_HelloWorld
   * @author      Muhammad Qaisar Satti
   * @Email       [email protected]
   *
*/
-->
<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">helloworld_edit.helloworld_data_source</item>
            <item name="deps" xsi:type="string">helloworld_edit.helloworld_data_source</item>
        </item>
        <item name="label" xsi:type="string" translate="true">Manage Post</item>
         <item name="config" xsi:type="array">
            <item name="dataScope" xsi:type="string">data</item>
            <item name="namespace" xsi:type="string">helloworld_edit</item>
        </item>
        <item name="template" xsi:type="string">templates/form/collapsible</item>
         <item name="buttons" xsi:type="array">
            <item name="back" xsi:type="string">QaisarSatti\HelloWorld\Block\Adminhtml\HelloWorld\Edit\BackButton</item>
            <item name="delete" xsi:type="string">QaisarSatti\HelloWorld\Block\Adminhtml\HelloWorld\Edit\DeleteButton</item>
            <item name="reset" xsi:type="string">QaisarSatti\HelloWorld\Block\Adminhtml\HelloWorld\Edit\ResetButton</item>
            <item name="save" xsi:type="string">QaisarSatti\HelloWorld\Block\Adminhtml\HelloWorld\Edit\SaveButton</item>
            <item name="save_and_continue" xsi:type="string">QaisarSatti\HelloWorld\Block\Adminhtml\HelloWorld\Edit\SaveAndContinueButton</item>
        </item>        
    </argument>
    <dataSource name="helloworld_data_source">
        <argument name="dataProvider" xsi:type="configurableObject">
            <argument name="class" xsi:type="string">QaisarSatti\HelloWorld\Model\HelloWorld\DataProvider</argument>
            <argument name="name" xsi:type="string">helloworld_data_source</argument>
            <argument name="primaryFieldName" xsi:type="string">post_id</argument>
            <argument name="requestFieldName" xsi:type="string">id</argument>
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="submit_url" xsi:type="url" path="helloworld/index/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">
        <argument name="data" xsi:type="array">
            <item name="config" xsi:type="array">
                <item name="label" xsi:type="string"/>
            </item>
        </argument>
        <field name="id">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="visible" xsi:type="boolean">false</item>
                    <item name="dataType" xsi:type="string">text</item>
                    <item name="formElement" xsi:type="string">input</item>
                    <item name="source" xsi:type="string">helloworld</item>
                </item>
            </argument>
        </field>
        <field name="title">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="label" xsi:type="string">Title:</item>
                    <item name="visible" xsi:type="boolean">true</item>
                    <item name="dataType" xsi:type="string">text</item>
                    <item name="formElement" xsi:type="string">input</item>
                    <item name="source" xsi:type="string">helloworld</item>
                    <item name="validation" xsi:type="array">
                        <item name="required-entry" xsi:type="boolean">true</item>
                    </item>
                </item>
            </argument>
        </field>
        <field name="content">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="label" xsi:type="string">Content:</item>
                    <item name="visible" xsi:type="boolean">true</item>
                    <item name="dataType" xsi:type="string">textarea</item>
                    <item name="formElement" xsi:type="string">textarea</item>
                    <item name="source" xsi:type="string">helloworld</item>
                </item>
            </argument>
        </field>        
     </fieldset>
 </form>

Save Form Data

Save controller have two parts. First is check PostDataProcessor, and second is save controller.

Post Data Processor

This is for validation purposes of form. Create PostDataProcessor.php in following directory

QaisarSatti\HelloWorld\Controller\Adminhtml\Index\

<?php
/**
 * Hello World
    *
    * @category    QaisarSatti
    * @package     QaisarSatti_HelloWorld
    * @author      Muhammad Qaisar Satti
    * @Email       [email protected]
    *
 */

namespace QaisarSatti\HelloWorld\Controller\Adminhtml\Index;

class PostDataProcessor
{
    /**
     * @var \Magento\Framework\Stdlib\DateTime\Filter\Date
     */

    protected $dateFilter;

    /**
     * @var \Magento\Framework\View\Model\Layout\Update\ValidatorFactory
     */

    protected $validatorFactory;

    /**
     * @var \Magento\Framework\Message\ManagerInterface
     */

    protected $messageManager;

    /**
     * @param \Magento\Framework\Stdlib\DateTime\Filter\Date $dateFilter
     * @param \Magento\Framework\Message\ManagerInterface $messageManager
     * @param \Magento\Framework\View\Model\Layout\Update\ValidatorFactory $validatorFactory
     */

    public function __construct(
        \Magento\Framework\Stdlib\DateTime\Filter\Date $dateFilter,
        \Magento\Framework\Message\ManagerInterface $messageManager,
        \Magento\Framework\View\Model\Layout\Update\ValidatorFactory $validatorFactory
    ) {
        $this->dateFilter = $dateFilter;
        $this->messageManager = $messageManager;
        $this->validatorFactory = $validatorFactory;
    }

    /**
     * Filtering posted data. Converting localized data if needed
     *
     * @param array $data
     * @return array
     */

    public function filter($data)
    {
        $filterRules = [];

        foreach (['custom_theme_from', 'custom_theme_to'] as $dateField) {
            if (!empty($data[$dateField])) {
                $filterRules[$dateField] = $this->dateFilter;
            }
        }

        return (new \Zend_Filter_Input($filterRules, [], $data))->getUnescaped();
    }

    /**
     * Validate post data
     *
     * @param array $data
     * @return bool     Return FALSE if someone item is invalid
     */

    public function validate($data)
    {
        $errorNo = true;
        if (!empty($data['layout_update_xml']) || !empty($data['custom_layout_update_xml'])) {
            /** @var $validatorCustomLayout \Magento\Framework\View\Model\Layout\Update\Validator */
            $validatorCustomLayout = $this->validatorFactory->create();
            if (!empty($data['layout_update_xml']) && !$validatorCustomLayout->isValid($data['layout_update_xml'])) {
                $errorNo = false;
            }
            if (!empty($data['custom_layout_update_xml'])
                && !$validatorCustomLayout->isValid($data['custom_layout_update_xml'])
            ) {
                $errorNo = false;
            }
            foreach ($validatorCustomLayout->getMessages() as $message) {
                $this->messageManager->addError($message);
            }
        }
        return $errorNo;
    }

    /**
     * Check if required fields is not empty
     *
     * @param array $data
     * @return bool
     */

    public function validateRequireEntry(array $data)
    {
        $requiredFields = [
            'title' => __('Title')
        ];
        $errorNo = true;
        foreach ($data as $field => $value) {
            if (in_array($field, array_keys($requiredFields)) && $value == '') {
                $errorNo = false;
                $this->messageManager->addError(
                    __('To apply changes you should fill in hidden required "%1" field', $requiredFields[$field])
                );
            }
        }
        return $errorNo;
    }
}

Form Save Data Controller

Now we save the data to our table.Create Save.php in following directory

QaisarSatti\HelloWorld\Controller\Adminhtml\Index\

<?php
/**
 * Hello World
    *
    * @category    QaisarSatti
    * @package     QaisarSatti_HelloWorld
    * @author      Muhammad Qaisar Satti
    * @Email       [email protected]
    *
 */

namespace QaisarSatti\HelloWorld\Controller\Adminhtml\Index;

use Magento\Backend\App\Action;
use QaisarSatti\HelloWorld\Model\HelloWorld;
use Magento\Framework\App\Request\DataPersistorInterface;
use Magento\Framework\Exception\LocalizedException;

class Save extends \Magento\Backend\App\Action
{
   
    const ADMIN_RESOURCE = 'QaisarSatti_HelloWorld::helloworld1';    
    protected $dataProcessor;    
    protected $dataPersistor;
    protected $model;

    public function __construct(
        Action\Context $context,
        PostDataProcessor $dataProcessor,
        HelloWorld $model,
        DataPersistorInterface $dataPersistor
    ) {
        $this->dataProcessor = $dataProcessor;
        $this->dataPersistor = $dataPersistor;
        $this->model = $model;
        parent::__construct($context);
    }

    public function execute()
    {
       
        $data = $this->getRequest()->getPostValue();
        $resultRedirect = $this->resultRedirectFactory->create();
        if ($data) {

            $data = $this->dataProcessor->filter($data);
           

            $id = $this->getRequest()->getParam('id');
            if ($id) {
                $this->model->load($id);
            }
           

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

            $this->_eventManager->dispatch(
                'helloworld_prepare_save',
                ['helloworld' => $this->model, 'request' => $this->getRequest()]
            );

            if (!$this->dataProcessor->validate($data)) {
                return $resultRedirect->setPath('*/*/edit', ['id' => $this->model->getId(), '_current' => true]);
            }

            try {
                $this->model->save();
                $this->messageManager->addSuccess(__('You saved the Post.'));
                $this->dataPersistor->clear('helloworld');
                if ($this->getRequest()->getParam('back')) {
                    return $resultRedirect->setPath(
                        '*/*/edit',
                        ['id' => $this->model->getId(),
                         '_current' => true]
                    );
                }
                return $resultRedirect->setPath('*/*/');
            } catch (LocalizedException $e) {
                $this->messageManager->addError($e->getMessage());
            } catch (\Exception $e) {
                $this->messageManager->addException($e, __('Something went wrong while saving the Post.'));
            }

            $this->dataPersistor->set('helloworld', $data);
            return $resultRedirect->setPath('*/*/edit', ['id' => $this->getRequest()->getParam('id')]);
        }
        return $resultRedirect->setPath('*/*/');
    }
}

Form Delete Button Controller

Create Delete.php in following directory

QaisarSatti\HelloWorld\Controller\Adminhtml\Index\

<?php
/**
 * Hello World
    *
    * @category    QaisarSatti
    * @package     QaisarSatti_HelloWorld
    * @author      Muhammad Qaisar Satti
    * @Email       [email protected]
    *
 */

namespace QaisarSatti\HelloWorld\Controller\Adminhtml\Index;

use Magento\Backend\App\Action;

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

    const ADMIN_RESOURCE = 'QaisarSatti_HelloWorld::helloworld1';
       
    protected $model;
    public function __construct(
        Action\Context $context,
        \QaisarSatti\HelloWorld\Model\HelloWorld $model
    ) {
        $this->model = $model;
        parent::__construct($context);
    }
    public function execute()
    {
        // check if we know what should be deleted
        $id = $this->getRequest()->getParam('id');
        /** @var \Magento\Backend\Model\View\Result\Redirect $resultRedirect */
        $resultRedirect = $this->resultRedirectFactory->create();
        if ($id) {
            $title = "";
            try {
                $this->model->load($id);
                $title = $this->model->getTitle();
                $this->model->delete();
                // display success message
                $this->messageManager->addSuccess(__('The post has been deleted.'));
                // go to grid
                $this->_eventManager->dispatch(
                    'adminhtml_helloworld_on_delete',
                    ['title' => $title, 'status' => 'success']
                );
                return $resultRedirect->setPath('*/*/');
            } catch (\Exception $e) {
                $this->_eventManager->dispatch(
                    'adminhtml_helloworld_on_delete',
                    ['title' => $title, 'status' => 'fail']
                );
                // display error message
                $this->messageManager->addError($e->getMessage());
                // go back to edit form
                return $resultRedirect->setPath('*/*/edit', ['id' => $id]);
            }
        }
        // display error message
        $this->messageManager->addError(__('We can\'t find a post to delete.'));
        // go to grid
        return $resultRedirect->setPath('*/*/');
    }
}

Now we complete the custom admin form. Now move to fourth part Magento 2 create basic module frontend part 4.

Author: Qaisar Satti
Category: Magento 2
Last Modified: February 9, 2018


Magento 2 create basic module admin grid part 2

Now we move to second part how in Magento 2 create basic module admin grid. As we cover the main part of module in Magento 2 create basic module part 1. Now we focus on admin part. This tutorial cover the how to create admin controller, how to create admin menu, how to create admin custom ui component grid, how to create admin ui component form,how to create mass action and how to create custom router for admin. So start with creating the router.

Admin Router

Now we define our custom frontName for admin.Now create routes.xml in following directory

QaisarSatti/HelloWorld/etc/adminhtml/

<?xml version="1.0"?>
<!--* Hello World
   *
   * @category    QaisarSatti
   * @package     QaisarSatti_HelloWorld
   * @author      Muhammad Qaisar Satti
   * @Email       [email protected]
   *
    -->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd">
    <router id="admin">
        <route id="helloworld" frontName="helloworld">
            <module name="QaisarSatti_HelloWorld" before="Magento_Backend" />
        </route>
    </router>
</config>

Admin Menu

Now we define our menu for admin.Now create menu.xml in following directory

QaisarSatti/HelloWorld/etc/adminhtml/

<?xml version="1.0"?>
<!--* Hello World
    *
    * @category    QaisarSatti
    * @package     QaisarSatti_HelloWorld
    * @author      Muhammad Qaisar Satti
    * @Email       [email protected]
    *
     -->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Backend:etc/menu.xsd">
    <menu>
            <update id="QaisarSatti_HelloWorld::helloworld" title="Qaisar Satti" module="Magento_Backend" sortOrder="177" resource="QaisarSatti_HelloWorld::helloworld"/>
            <add id="QaisarSatti_HelloWorld::helloworldparent" title="Qaisar Satti" module="QaisarSatti_HelloWorld" sortOrder="72"  parent="QaisarSatti_HelloWorld::helloworld" resource="QaisarSatti_HelloWorld::helloworldparent" />
            <add id="QaisarSatti_HelloWorld::helloworld1" title="Manage Blog Post" module="QaisarSatti_HelloWorld" sortOrder="0" parent="QaisarSatti_HelloWorld::helloworldparent" action="helloworld/" resource="QaisarSatti_HelloWorld::helloworld1"/>
    </menu>
</config>

Admin Grid

Now we create custom grid admin.If you want to read the detail about read tutorial Magento 2 create admin controller. Grid is part of three files. Controller file, layout file, grid collection model and ui component file.

Grid Controller

i am creating the grid on my Index.php action. As follow my module create Index.php in following directory

QaisarSatti\HelloWorld\Controller\Adminhtml\Index

<?php
/**
 * Hello World
    *
    * @category    QaisarSatti
    * @package     QaisarSatti_HelloWorld
    * @author      Muhammad Qaisar Satti
    * @Email       [email protected]
    *
 */

namespace QaisarSatti\HelloWorld\Controller\Adminhtml\Index;

class Index extends \Magento\Backend\App\Action
{
   
    protected $resultPageFactory;

   
    public function __construct(
        \Magento\Backend\App\Action\Context $context,
        \Magento\Framework\Registry $coreRegistry,
        \Magento\Framework\View\Result\PageFactory $resultPageFactory
    ) {
        $this->resultPageFactory = $resultPageFactory;
        parent::__construct($context, $coreRegistry);
    }

   
    public function execute()
    {

        $resultPage = $this->resultPageFactory->create();
        $this->initPage($resultPage)->getConfig()->getTitle()->prepend(__('Manage Post'));
        return $resultPage;
    }
    protected function initPage($resultPage)
    {
         $resultPage->setActiveMenu('QaisarSatti_HelloWorld::helloworld1')
             ->addBreadcrumb(__('Qaisar Satti'), __('Qaisar Satti'))
             ->addBreadcrumb(__('Manage Post'), __('Manage Post'));

         return $resultPage;
    }

 
    protected function _isAllowed()
    {
        return $this->_authorization->isAllowed('QaisarSatti_HelloWorld::helloworld1');
    }
}

Grid layout

Now we create the grid layout file that connect it with ui component. Our ui component file name is helloworld_listing. So create helloworld_index_index.xml in following directory

QaisarSatti\HelloWorld\view\adminhtml\layout

<?xml version="1.0"?>
<!--
   /**
   * Hello World
   *
   * @category    QaisarSatti
   * @package     QaisarSatti_HelloWorld
   * @author      Muhammad Qaisar Satti
   * @Email       [email protected]
   *
*/
-->
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <body>
       <referenceContainer name="content">
            <uiComponent name="helloworld_listing"/>
        </referenceContainer>
     
    </body>
</page>

Grid Collection Model

For the grid you need to create grid collection model.This collection have method that used for grid. Create Collection.php in following directory

QaisarSatti\HelloWorld\Model\ResourceModel\HelloWorld\Grid\

<?php
/**
 * Hello World
    *
    * @category    QaisarSatti
    * @package     QaisarSatti_HelloWorld
    * @author      Muhammad Qaisar Satti
    * @Email       [email protected]
    *
 */

namespace QaisarSatti\HelloWorld\Model\ResourceModel\HelloWorld\Grid;

use Magento\Framework\Api\Search\SearchResultInterface;
use Magento\Framework\Api\Search\AggregationInterface;
use QaisarSatti\HelloWorld\Model\ResourceModel\HelloWorld\Collection as HelloWorldCollection;

/**
 * Class Collection
 * Collection for displaying grid of sales documents
 */

class Collection extends HelloWorldCollection implements SearchResultInterface
{
    /**
     * @var AggregationInterface
     */

    protected $aggregations;

    /**
     * @param \Magento\Framework\Data\Collection\EntityFactoryInterface $entityFactory
     * @param \Psr\Log\LoggerInterface $logger
     * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
     * @param \Magento\Framework\Event\ManagerInterface $eventManager
     * @param \Magento\Store\Model\StoreManagerInterface $storeManager
     * @param \Magento\Framework\EntityManager\MetadataPool $metadataPool
     * @param mixed|null $mainTable
     * @param \Magento\Framework\Model\ResourceModel\Db\AbstractDb $eventPrefix
     * @param mixed $eventObject
     * @param mixed $resourceModel
     * @param string $model
     * @param null $connection
     * @param \Magento\Framework\Model\ResourceModel\Db\AbstractDb|null $resource
     *
     * @SuppressWarnings(PHPMD.ExcessiveParameterList)
     */

    public function __construct(
        \Magento\Framework\Data\Collection\EntityFactoryInterface $entityFactory,
        \Psr\Log\LoggerInterface $logger,
        \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
        \Magento\Framework\Event\ManagerInterface $eventManager,
        \Magento\Store\Model\StoreManagerInterface $storeManager,
        \Magento\Framework\EntityManager\MetadataPool $metadataPool,
        $mainTable,
        $eventPrefix,
        $eventObject,
        $resourceModel,
        $model = 'Magento\Framework\View\Element\UiComponent\DataProvider\Document',
        $connection = null,
        \Magento\Framework\Model\ResourceModel\Db\AbstractDb $resource = null
    ) {
        parent::__construct(
            $entityFactory,
            $logger,
            $fetchStrategy,
            $eventManager,
            $storeManager,
            $metadataPool,
            $connection,
            $resource
        );
        $this->_eventPrefix = $eventPrefix;
        $this->_eventObject = $eventObject;
        $this->_init($model, $resourceModel);
        $this->setMainTable($mainTable);
    }

    /**
     * @return AggregationInterface
     */

    public function getAggregations()
    {
        return $this->aggregations;
    }

    /**
     * @param AggregationInterface $aggregations
     * @return $this
     */

    public function setAggregations($aggregations)
    {
        $this->aggregations = $aggregations;
    }

    /**
     * Get search criteria.
     *
     * @return \Magento\Framework\Api\SearchCriteriaInterface|null
     */

    public function getSearchCriteria()
    {
        return null;
    }

    /**
     * Set search criteria.
     *
     * @param \Magento\Framework\Api\SearchCriteriaInterface $searchCriteria
     * @return $this
     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
     */

    public function setSearchCriteria(\Magento\Framework\Api\SearchCriteriaInterface $searchCriteria = null)
    {
        return $this;
    }

    /**
     * Get total count.
     *
     * @return int
     */

    public function getTotalCount()
    {
        return $this->getSize();
    }

    /**
     * Set total count.
     *
     * @param int $totalCount
     * @return $this
     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
     */

    public function setTotalCount($totalCount)
    {
        return $this;
    }

    /**
     * Set items list.
     *
     * @param \Magento\Framework\Api\ExtensibleDataInterface[] $items
     * @return $this
     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
     */

    public function setItems(array $items = null)
    {
        return $this;
    }
}

Define Data Source and Data Provider

Now we define data source for grid. Our dataSource name will be helloworld_listing_data_source and DataProvider name helloworldGridDataProvider.create di.xml in following directory

QaisarSatti\HelloWorld\etc\\

<?xml version="1.0"?>
<!--
/**
* Hello World
   *
   * @category    QaisarSatti
   * @package     QaisarSatti_HelloWorld
   * @author      Muhammad Qaisar Satti
   * @Email       [email protected]
   *
*/
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
   <type name="Magento\Framework\View\Element\UiComponent\DataProvider\CollectionFactory">
        <arguments>
            <argument name="collections" xsi:type="array">
                <item name="helloworld_listing_data_source" xsi:type="string">QaisarSatti\HelloWorld\Model\ResourceModel\HelloWorld\Grid\Collection</item>
            </argument>
        </arguments>
    </type>
    <type name="QaisarSatti\HelloWorld\Model\ResourceModel\HelloWorld\Grid\Collection">
        <arguments>
            <argument name="mainTable" xsi:type="string">sample_posts</argument>
            <argument name="eventPrefix" xsi:type="string">helloworld_grid_collection</argument>
            <argument name="eventObject" xsi:type="string">helloworld_grid_collection</argument>
            <argument name="resourceModel" xsi:type="string">QaisarSatti\HelloWorld\Model\ResourceModel\HelloWorld</argument>
        </arguments>
    </type>
    <virtualType name="helloworldGirdFilterPool" 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="helloworldGridDataProvider" type="Magento\Framework\View\Element\UiComponent\DataProvider\DataProvider">
        <arguments>
            <argument name="collection" xsi:type="object" shared="false">QaisarSatti\HelloWorld\Model\ResourceModel\HelloWorld\Collection</argument>
            <argument name="filterPool" xsi:type="object" shared="false">helloworldGirdFilterPool</argument>
        </arguments>
    </virtualType>
   
 
</config>

Grid Action Column Url Builder

create UrlBuilder.php in following directory

QaisarSatti\HelloWorld\Block\Adminhtml\HelloWorld\Grid\Renderer\Action\

<?php
/**
 * Hello World
    *
    * @category    QaisarSatti
    * @package     QaisarSatti_HelloWorld
    * @author      Muhammad Qaisar Satti
    * @Email       [email protected]
    *
 */

namespace QaisarSatti\HelloWorld\Block\Adminhtml\HelloWorld\Grid\Renderer\Action;

class UrlBuilder
{
    /**
     * @var \Magento\Framework\UrlInterface
     */

    protected $frontendUrlBuilder;

    /**
     * @param \Magento\Framework\UrlInterface $frontendUrlBuilder
     */

    public function __construct(\Magento\Framework\UrlInterface $frontendUrlBuilder)
    {
        $this->frontendUrlBuilder = $frontendUrlBuilder;
    }

    /**
     * Get action url
     *
     * @param string $routePath
     * @param string $scope
     * @param string $store
     * @return string
     */

    public function getUrl($routePath, $scope, $store)
    {
        $this->frontendUrlBuilder->setScope($scope);
        $href = $this->frontendUrlBuilder->getUrl(
            $routePath,
            ['_current' => false, '_query' => '___store=' . $store]
        );
        return $href;
    }
}

Grid Action Column

This will be used in action column of grid. You can add edit or any action you want to perform with current row data. create HelloWorldActions.php in following directory

QaisarSatti\HelloWorld\Ui\Component\Listing\Column\

<?php
/**
 * Hello World
    *
    * @category    QaisarSatti
    * @package     QaisarSatti_HelloWorld
    * @author      Muhammad Qaisar Satti
    * @Email       [email protected]
    *
 */

namespace QaisarSatti\HelloWorld\Ui\Component\Listing\Column;

use Magento\Framework\View\Element\UiComponent\ContextInterface;
use Magento\Framework\View\Element\UiComponentFactory;
use Magento\Ui\Component\Listing\Columns\Column;
use QaisarSatti\HelloWorld\Block\Adminhtml\HelloWorld\Grid\Renderer\Action\UrlBuilder;
use Magento\Framework\UrlInterface;

/**
 * Class PageActions
 */

class HelloWorldActions extends Column
{
    /** Url path */
    const HELLOWORLD_URL_PATH_EDIT = 'helloworld/index/edit';
    const HELLOWORLD_URL_PATH_DELETE = 'helloworld/index/delete';

    /** @var UrlBuilder */
    protected $actionUrlBuilder;

    /** @var UrlInterface */
    protected $urlBuilder;

    /**
     * @var string
     */

    private $editUrl;

    /**
     * @param ContextInterface $context
     * @param UiComponentFactory $uiComponentFactory
     * @param UrlBuilder $actionUrlBuilder
     * @param UrlInterface $urlBuilder
     * @param array $components
     * @param array $data
     * @param string $editUrl
     */

    public function __construct(
        ContextInterface $context,
        UiComponentFactory $uiComponentFactory,
        UrlBuilder $actionUrlBuilder,
        UrlInterface $urlBuilder,
        array $components = [],
        array $data = [],
        $editUrl = self::HELLOWORLD_URL_PATH_EDIT
    ) {
        $this->urlBuilder = $urlBuilder;
        $this->actionUrlBuilder = $actionUrlBuilder;
        $this->editUrl = $editUrl;
        parent::__construct($context, $uiComponentFactory, $components, $data);
    }

    /**
     * Prepare Data Source
     *
     * @param array $dataSource
     * @return array
     */

    public function prepareDataSource(array $dataSource)
    {
        if (isset($dataSource['data']['items'])) {
            foreach ($dataSource['data']['items'] as & $item) {
                $name = $this->getData('name');
                if (isset($item['post_id'])) {
                    $item[$name]['edit'] = [
                        'href' => $this->urlBuilder->getUrl($this->editUrl, ['id' => $item['post_id']]),
                        'label' => __('Edit')
                    ];
                    $item[$name]['delete'] = [
                        'href' => $this->urlBuilder->getUrl(self::HELLOWORLD_URL_PATH_DELETE, ['id' => $item['post_id']]),
                        'label' => __('Delete'),
                        'confirm' => [
                            'title' => __('Delete ${ $.$data.title }'),
                            'message' => __('Are you sure you wan\'t to delete a ${ $.$data.title } record?')
                        ]
                    ];
 
                }
            }

        return $dataSource;
        }
    }
}

Grid Ui Component

I already posted the detail article about Magento 2 create custom ui component admin grid. So we not going to detail explanation about it. So move on with create helloworld_listing.xml in following directory

QaisarSatti\HelloWorld\view\adminhtml\ui_component\

<?xml version="1.0" encoding="UTF-8"?>
<!--
/**
* Hello World
   *
   * @category    QaisarSatti
   * @package     QaisarSatti_HelloWorld
   * @author      Muhammad Qaisar Satti
   * @Email       [email protected]
   *
*/
-->
<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">helloworld_listing.helloworld_listing_data_source</item>
            <item name="deps" xsi:type="string">helloworld_listing.helloworld_listing_data_source</item>
        </item>
        <item name="spinner" xsi:type="string">helloworld_index_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 Blog Post</item>
                <item name="class" xsi:type="string">primary</item>
                <item name="url" xsi:type="string">*/*/new</item>
            </item>
        </item>
    </argument>
    <dataSource name="helloworld_listing_data_source">
        <argument name="dataProvider" xsi:type="configurableObject">
            <argument name="class" xsi:type="string">helloworldGridDataProvider</argument>
            <argument name="name" xsi:type="string">helloworld_listing_data_source</argument>
            <argument name="primaryFieldName" xsi:type="string">post_id</argument>
            <argument name="requestFieldName" xsi:type="string">id</argument>
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                <item name="component" xsi:type="string">Magento_Ui/js/grid/provider</item>
                    <item name="update_url" xsi:type="url" path="mui/index/render"/>
                </item>
            </argument>
        </argument>
    </dataSource>
    <listingToolbar name="listing_top">
        <argument name="data" xsi:type="array">
            <item name="config" xsi:type="array">
                <item name="sticky" xsi:type="boolean">true</item>
            </item>
        </argument>
        <bookmark name="bookmarks"/>
        <columnsControls name="columns_controls"/>
        <filterSearch name="fulltext"/>
        <filters name="listing_filters">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="columnsProvider" xsi:type="string">helloworld_listing.helloworld_listing.helloworld_index_columns</item>
                    <item name="storageConfig" xsi:type="array">
                        <item name="provider" xsi:type="string">storageConfig.storageConfig.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">storageConfig.storageConfig.listing_top.listing_filters</item>
                        <item name="imports" xsi:type="array">
                            <item name="visible" xsi:type="string">storageConfig.storageConfig.helloworld_index_columns.${ $.index }:visible</item>
                        </item>
                    </item>
                </item>
                <item name="observers" xsi:type="array">
                    <item name="column" xsi:type="string">column</item>
                </item>
            </argument>
        </filters>
        <massaction name="listing_massaction">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="selectProvider" xsi:type="string">helloworld_listing.helloworld_listing.helloworld_index_columns.ids</item>
                    <item name="indexField" xsi:type="string">post_id</item>
                </item>
            </argument>
            <action name="delete">
                <argument name="data" xsi:type="array">
                    <item name="config" xsi:type="array">
                        <item name="type" xsi:type="string">delete</item>
                        <item name="label" xsi:type="string" translate="true">Delete</item>
                        <item name="url" xsi:type="url" path="helloworld/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>
        </massaction>
        <paging name="listing_paging"/>
    </listingToolbar>
   
    <columns name="helloworld_index_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">helloworld_listing.helloworld_listing.listing_top.bookmarks</item>
                    <item name="namespace" xsi:type="string">current</item>
                </item>
                <item name="editorConfig" xsi:type="array">
                    <item name="selectProvider" xsi:type="string">helloworld_listing.helloworld_listing.helloworld_index_columns.ids</item>
                    <item name="enabled" xsi:type="boolean">true</item>
                    <item name="indexField" xsi:type="string">id</item>
                    <item name="clientConfig" xsi:type="array">
                        <item name="saveUrl" xsi:type="url" path="news/index/inlineEdit"/>
                        <item name="validateBeforeSave" xsi:type="boolean">false</item>
                    </item>
                </item>
                <item name="childDefaults" xsi:type="array">
                    <item name="fieldAction" xsi:type="array">
                        <item name="provider" xsi:type="string">helloworld_listing.helloworld_listing.helloworld_index_columns_editor</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">helloworld_listing.helloworld_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">post_id</item>
                </item>
            </argument>
        </selectionsColumn>
        <column name="title">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="filter" xsi:type="string">text</item>
                    <item name="editor" xsi:type="array">
                        <item name="editorType" xsi:type="string">text</item>
                        <item name="validation" xsi:type="array">
                            <item name="required-entry" xsi:type="boolean">true</item>
                        </item>
                    </item>
                    <item name="label" xsi:type="string" translate="true">Title</item>
                </item>
            </argument>
        </column>
         <column name="content">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="editor" xsi:type="array">
                        <item name="editorType" xsi:type="string">textarea</item>
                        <item name="validation" xsi:type="array">
                            <item name="required-entry" xsi:type="boolean">true</item>
                        </item>
                    </item>
                    <item name="label" xsi:type="string" translate="true">Content</item>
                </item>
            </argument>
        </column>  
        <actionsColumn name="actions" class="QaisarSatti\HelloWorld\Ui\Component\Listing\Column\HelloWorldActions">
            <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">post_id</item>
                </item>
            </argument>
        </actionsColumn>
    </columns>
    <container name="sticky">
        <argument name="data" xsi:type="array">
            <item name="config" xsi:type="array">
                <item name="component" xsi:type="string">Magento_Ui/js/grid/sticky/sticky</item>
                <item name="toolbarProvider" xsi:type="string">helloworld_listing.helloworld_listing.listing_top</item>
                <item name="listingProvider" xsi:type="string">helloworld_listing.helloworld_listing.helloworld_index_columns</item>
            </item>
        </argument>
    </container>
</listing>

Grid Mass Action

Now we create the mass action controller for grid. You can any mass action like enabled, disabled and any other mass action. Now i am creating mass delete action. Create controller for MassDelete.php in following directory

QaisarSatti\HelloWorld\Controller\Adminhtml\Index\

<?php
/**
 * Hello World
    *
    * @category    QaisarSatti
    * @package     QaisarSatti_HelloWorld
    * @author      Muhammad Qaisar Satti
    * @Email       [email protected]
    *
 */

namespace QaisarSatti\HelloWorld\Controller\Adminhtml\Index;

use Magento\Framework\Controller\ResultFactory;
use Magento\Backend\App\Action\Context;
use Magento\Ui\Component\MassAction\Filter;
use QaisarSatti\HelloWorld\Model\ResourceModel\HelloWorld\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 $page) {
            $page->delete();
        }

        $this->messageManager->addSuccess(__('A total of %1 record(s) have been deleted.', $collectionSize));

        /** @var \Magento\Backend\Model\View\Result\Redirect $resultRedirect */
        $resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT);
        return $resultRedirect->setPath('*/*/');
    }
}

Now we complete the custom admin grid. Now move to third part Magento 2 create basic module admin from part 3.

Author: Qaisar Satti
Category: Magento 2
Last Modified: February 9, 2018


Magento 2 create custom ui component admin grid

Today we talk about How in Magento 2 create custom ui component admin grid. For creating the grid you must familiar with ui component of magento2. The grid consist of these major node that must be used for creating the grid.

Data Argument

The argument data basically have three item js_config,buttons and spinner. Js_config contain js configuration of grid data. In buttons you can add button that are need to added into grid like add or import like this.spinner have to added on your columns you have to add you column name.

js_config

helloworld_listing this will be you ui component file name. helloworld_listing_data_source will be name of your dataSource.

<item name="js_config" xsi:type="array">
            <item name="provider" xsi:type="string">helloworld_listing.helloworld_listing_data_source</item>
            <item name="deps" xsi:type="string">pomanager_listing.helloworld_listing_data_source</item>
        </item>

buttons

You can add button in your grid in buttons 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 Blog Post</item>
                <item name="class" xsi:type="string">primary</item>
                <item name="url" xsi:type="string">*/*/new</item>
            </item>
        </item>

spinner

This have configuration where spinner will be load that contain columns name example helloworld_index_columns.

        <item name="spinner" xsi:type="string">helloworld_index_columns</item>

dataSource

Second component of ui component grid is dataSource. That have unique name that are use in ui component grid. Name of my example helloworld_listing_data_source.

<dataSource name="helloworld_listing_data_source">
        <argument name="dataProvider" xsi:type="configurableObject">
            <argument name="class" xsi:type="string">helloworldGridDataProvider</argument>
            <argument name="name" xsi:type="string">helloworld_listing_data_source</argument>
            <argument name="primaryFieldName" xsi:type="string">post_id</argument>
            <argument name="requestFieldName" xsi:type="string">id</argument>
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                <item name="component" xsi:type="string">Magento_Ui/js/grid/provider</item>
                    <item name="update_url" xsi:type="url" path="mui/index/render"/>
                </item>
            </argument>
        </argument>
</dataSource>

listingToolbar

Toolbar is included many argument like bookmarks,columnsControls, filterSearch,filters,paging and massaction.

massaction

In massaction you add the mass action options like delete, edit or enable disbaled.

<massaction name="listing_massaction">
            <action name="delete">
                <argument name="data" xsi:type="array">
                    <item name="config" xsi:type="array">
                        <item name="type" xsi:type="string">delete</item>
                        <item name="label" xsi:type="string" translate="true">Delete</item>
                        <item name="url" xsi:type="url" path="helloworld/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 want to delete selected items?</item>
                        </item>
                    </item>
                </argument>
            </action>
</massaction>

Example of listing toolbar

<listingToolbar name="listing_top">
        <argument name="data" xsi:type="array">
            <item name="config" xsi:type="array">
                <item name="sticky" xsi:type="boolean">true</item>
            </item>
        </argument>
        <bookmark name="bookmarks"/>
        <columnsControls name="columns_controls"/>
        <filterSearch name="fulltext"/>
        <filters name="listing_filters">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="columnsProvider" xsi:type="string">helloworld_listing.helloworld_listing.helloworld_index_columns</item>
                    <item name="storageConfig" xsi:type="array">
                        <item name="provider" xsi:type="string">storageConfig.storageConfig.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">storageConfig.storageConfig.listing_top.listing_filters</item>
                        <item name="imports" xsi:type="array">
                            <item name="visible" xsi:type="string">storageConfig.storageConfig.helloworld_index_columns.${ $.index }:visible</item>
                        </item>
                    </item>
                </item>
                <item name="observers" xsi:type="array">
                    <item name="column" xsi:type="string">column</item>
                </item>
            </argument>
        </filters>
        <massaction name="listing_massaction">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="selectProvider" xsi:type="string">helloworld_listing.helloworld_listing.helloworld_index_columns.ids</item>
                    <item name="indexField" xsi:type="string">post_id</item>
                </item>
            </argument>
            <action name="delete">
                <argument name="data" xsi:type="array">
                    <item name="config" xsi:type="array">
                        <item name="type" xsi:type="string">delete</item>
                        <item name="label" xsi:type="string" translate="true">Delete</item>
                        <item name="url" xsi:type="url" path="helloworld/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 want to delete selected items?</item>
                        </item>
                    </item>
                </argument>
            </action>
        </massaction>
        <paging name="listing_paging"/>
    </listingToolbar>

columns

In column you must have the unique name like helloworld_index_columns. That are use other argument too. It’s depend on three argument data, selectionsColumn,actionsColumn and column. Example

<columns name="helloworld_index_columns">
</columns>

selectionsColumn

This is use for selection of grid columns.

<selectionsColumn name="ids">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="resizeEnabled" xsi:type="boolean">false</item>
                    <item name="resizeDefaultWidth" xsi:type="string">55</item>
                    <item name="indexField" xsi:type="string">post_id</item>
                </item>
            </argument>
   </selectionsColumn>

column

This will show the id in column
Example

<column name="title">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="filter" xsi:type="string">text</item>
                    <item name="editor" xsi:type="array">
                        <item name="editorType" xsi:type="string">text</item>
                        <item name="validation" xsi:type="array">
                            <item name="required-entry" xsi:type="boolean">true</item>
                        </item>
                    </item>
                    <item name="label" xsi:type="string" translate="true">Title</item>
                </item>
            </argument>
</column>

actionsColumn

This will use for delete,edit or any other functionality to perform with current row.
Example

<actionsColumn name="actions" class="QaisarSatti\HelloWorld\Ui\Component\Listing\Column\HelloWorldActions">
            <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">post_id</item>
                </item>
            </argument>
</actionsColumn>

Now complete example of ui_component grid

<?xml version="1.0" encoding="UTF-8"?>
<!--
/**
 * Copyright © 2016 Magento. All rights reserved.
 * See COPYING.txt for license details.
 */
-->
<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">helloworld_listing.helloworld_listing_data_source</item>
            <item name="deps" xsi:type="string">helloworld_listing.helloworld_listing_data_source</item>
        </item>
        <item name="spinner" xsi:type="string">helloworld_index_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 Blog Post</item>
                <item name="class" xsi:type="string">primary</item>
                <item name="url" xsi:type="string">*/*/new</item>
            </item>
        </item>
    </argument>
    <dataSource name="helloworld_listing_data_source">
        <argument name="dataProvider" xsi:type="configurableObject">
            <argument name="class" xsi:type="string">helloworldGridDataProvider</argument>
            <argument name="name" xsi:type="string">helloworld_listing_data_source</argument>
            <argument name="primaryFieldName" xsi:type="string">post_id</argument>
            <argument name="requestFieldName" xsi:type="string">id</argument>
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                <item name="component" xsi:type="string">Magento_Ui/js/grid/provider</item>
                    <item name="update_url" xsi:type="url" path="mui/index/render"/>
                </item>
            </argument>
        </argument>
    </dataSource>
    <listingToolbar name="listing_top">
        <argument name="data" xsi:type="array">
            <item name="config" xsi:type="array">
                <item name="sticky" xsi:type="boolean">true</item>
            </item>
        </argument>
        <bookmark name="bookmarks"/>
        <columnsControls name="columns_controls"/>
        <filterSearch name="fulltext"/>
        <filters name="listing_filters">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="columnsProvider" xsi:type="string">helloworld_listing.helloworld_listing.helloworld_index_columns</item>
                    <item name="storageConfig" xsi:type="array">
                        <item name="provider" xsi:type="string">storageConfig.storageConfig.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">storageConfig.storageConfig.listing_top.listing_filters</item>
                        <item name="imports" xsi:type="array">
                            <item name="visible" xsi:type="string">storageConfig.storageConfig.helloworld_index_columns.${ $.index }:visible</item>
                        </item>
                    </item>
                </item>
                <item name="observers" xsi:type="array">
                    <item name="column" xsi:type="string">column</item>
                </item>
            </argument>
        </filters>
        <massaction name="listing_massaction">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="selectProvider" xsi:type="string">helloworld_listing.helloworld_listing.helloworld_index_columns.ids</item>
                    <item name="indexField" xsi:type="string">post_id</item>
                </item>
            </argument>
            <action name="delete">
                <argument name="data" xsi:type="array">
                    <item name="config" xsi:type="array">
                        <item name="type" xsi:type="string">delete</item>
                        <item name="label" xsi:type="string" translate="true">Delete</item>
                        <item name="url" xsi:type="url" path="helloworld/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>
        </massaction>
        <paging name="listing_paging"/>
    </listingToolbar>
   
    <columns name="helloworld_index_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">helloworld_listing.helloworld_listing.listing_top.bookmarks</item>
                    <item name="namespace" xsi:type="string">current</item>
                </item>
                <item name="editorConfig" xsi:type="array">
                    <item name="selectProvider" xsi:type="string">helloworld_listing.helloworld_listing.helloworld_index_columns.ids</item>
                    <item name="enabled" xsi:type="boolean">true</item>
                    <item name="indexField" xsi:type="string">id</item>
                    <item name="clientConfig" xsi:type="array">
                        <item name="saveUrl" xsi:type="url" path="news/index/inlineEdit"/>
                        <item name="validateBeforeSave" xsi:type="boolean">false</item>
                    </item>
                </item>
                <item name="childDefaults" xsi:type="array">
                    <item name="fieldAction" xsi:type="array">
                        <item name="provider" xsi:type="string">helloworld_listing.helloworld_listing.helloworld_index_columns_editor</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">helloworld_listing.helloworld_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">post_id</item>
                </item>
            </argument>
        </selectionsColumn>
        <column name="title">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="filter" xsi:type="string">text</item>
                    <item name="editor" xsi:type="array">
                        <item name="editorType" xsi:type="string">text</item>
                        <item name="validation" xsi:type="array">
                            <item name="required-entry" xsi:type="boolean">true</item>
                        </item>
                    </item>
                    <item name="label" xsi:type="string" translate="true">Title</item>
                </item>
            </argument>
        </column>
         <column name="content">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="editor" xsi:type="array">
                        <item name="editorType" xsi:type="string">textarea</item>
                        <item name="validation" xsi:type="array">
                            <item name="required-entry" xsi:type="boolean">true</item>
                        </item>
                    </item>
                    <item name="label" xsi:type="string" translate="true">Content</item>
                </item>
            </argument>
        </column>  
        <actionsColumn name="actions" class="QaisarSatti\HelloWorld\Ui\Component\Listing\Column\HelloWorldActions">
            <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">post_id</item>
                </item>
            </argument>
        </actionsColumn>
    </columns>
    <container name="sticky">
        <argument name="data" xsi:type="array">
            <item name="config" xsi:type="array">
                <item name="component" xsi:type="string">Magento_Ui/js/grid/sticky/sticky</item>
                <item name="toolbarProvider" xsi:type="string">helloworld_listing.helloworld_listing.listing_top</item>
                <item name="listingProvider" xsi:type="string">helloworld_listing.helloworld_listing.helloworld_index_columns</item>
            </item>
        </argument>
    </container>
</listing>
Author: Qaisar Satti
Category: Magento 2
Last Modified: February 9, 2018


Magento 2 create custom ui component admin form

Today we talk about How in Magento 2 create custom ui component admin form. For creating the admin from you must familiar with ui component of magento2. The form consist of these major node that must be used for creating the form.

Data Argument

The argument data basically have three item js_config,label,config,template and buttons. Js_config contain js configuration of grid data. In buttons you can add button that are need to added into form like save button, delete button , save and continue button, reset button or any custom button as your requirement.

js_config

helloworld_listing this will be you ui component file name. helloworld_listing_data_source will be name of your dataSource.

<item name="js_config" xsi:type="array">
            <item name="provider" xsi:type="string">helloworld_edit.helloworld_data_source</item>
            <item name="deps" xsi:type="string">helloworld_edit.helloworld_data_source</item>
</item>

buttons

You can add button in your form in buttons item. like save button, delete button , save and continue button, reset button or any custom button as your requirement.

 <item name="buttons" xsi:type="array">
            <item name="back" xsi:type="string">QaisarSatti\HelloWorld\Block\Adminhtml\HelloWorld\Edit\BackButton</item>
</item>

template

You can set template type in this node.

       <item name="template" xsi:type="string">templates/form/collapsible</item>

label

<item name="label" xsi:type="string" translate="true">Manage Post</item>

config

<item name="config" xsi:type="array">
            <item name="dataScope" xsi:type="string">data</item>
            <item name="namespace" xsi:type="string">helloworld_edit</item>
 </item>

dataSource

Second component of ui component form is dataSource. That have unique name that are use in ui component from. Name of my example helloworld_data_source.

<dataSource name="helloworld_data_source">
        <argument name="dataProvider" xsi:type="configurableObject">
            <argument name="class" xsi:type="string">QaisarSatti\HelloWorld\Model\HelloWorld\DataProvider</argument>
            <argument name="name" xsi:type="string">helloworld_data_source</argument>
            <argument name="primaryFieldName" xsi:type="string">post_id</argument>
            <argument name="requestFieldName" xsi:type="string">id</argument>
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="submit_url" xsi:type="url" path="helloworld/index/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

You can add multiple fieldset in form. Fieldset have unique name like general. Fieldset consist of following elements.

Data argument

In data argument you can add the label for fieldset and sort order.

<argument name="data" xsi:type="array">
            <item name="config" xsi:type="array">
                <item name="collapsible" xsi:type="boolean">true</item>
                <item name="label" xsi:type="string" translate="true">General Information</item>
                <item name="sortOrder" xsi:type="number">20</item>
            </item>
</argument>

Field

This is element you add field as your requirement like select, input and etc. Here is simple example of field.

<field name="title">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="label" xsi:type="string">Title:</item>
                    <item name="visible" xsi:type="boolean">true</item>
                    <item name="dataType" xsi:type="string">text</item>
                    <item name="formElement" xsi:type="string">input</item>
                    <item name="source" xsi:type="string">helloworld</item>
                    <item name="validation" xsi:type="array">
                        <item name="required-entry" xsi:type="boolean">true</item>
                    </item>
                </item>
            </argument>
 </field>

Complete example for ui component is below.

<?xml version="1.0" encoding="UTF-8"?>
<!--
/**
 * Copyright © 2015 Magento. All rights reserved.
 * See COPYING.txt for license details.
 */
-->
<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">helloworld_edit.helloworld_data_source</item>
            <item name="deps" xsi:type="string">helloworld_edit.helloworld_data_source</item>
        </item>
        <item name="label" xsi:type="string" translate="true">Manage Post</item>
         <item name="config" xsi:type="array">
            <item name="dataScope" xsi:type="string">data</item>
            <item name="namespace" xsi:type="string">helloworld_edit</item>
        </item>
        <item name="template" xsi:type="string">templates/form/collapsible</item>
         <item name="buttons" xsi:type="array">
            <item name="back" xsi:type="string">QaisarSatti\HelloWorld\Block\Adminhtml\HelloWorld\Edit\BackButton</item>
            <item name="delete" xsi:type="string">QaisarSatti\HelloWorld\Block\Adminhtml\HelloWorld\Edit\DeleteButton</item>
            <item name="reset" xsi:type="string">QaisarSatti\HelloWorld\Block\Adminhtml\HelloWorld\Edit\ResetButton</item>
            <item name="save" xsi:type="string">QaisarSatti\HelloWorld\Block\Adminhtml\HelloWorld\Edit\SaveButton</item>
            <item name="save_and_continue" xsi:type="string">QaisarSatti\HelloWorld\Block\Adminhtml\HelloWorld\Edit\SaveAndContinueButton</item>
        </item>        
    </argument>
    <dataSource name="helloworld_data_source">
        <argument name="dataProvider" xsi:type="configurableObject">
            <argument name="class" xsi:type="string">QaisarSatti\HelloWorld\Model\HelloWorld\DataProvider</argument>
            <argument name="name" xsi:type="string">helloworld_data_source</argument>
            <argument name="primaryFieldName" xsi:type="string">post_id</argument>
            <argument name="requestFieldName" xsi:type="string">id</argument>
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="submit_url" xsi:type="url" path="helloworld/index/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">
        <argument name="data" xsi:type="array">
            <item name="config" xsi:type="array">
                <item name="label" xsi:type="string"/>
            </item>
        </argument>
        <field name="id">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="visible" xsi:type="boolean">false</item>
                    <item name="dataType" xsi:type="string">text</item>
                    <item name="formElement" xsi:type="string">input</item>
                    <item name="source" xsi:type="string">helloworld</item>
                </item>
            </argument>
        </field>
        <field name="title">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="label" xsi:type="string">Title:</item>
                    <item name="visible" xsi:type="boolean">true</item>
                    <item name="dataType" xsi:type="string">text</item>
                    <item name="formElement" xsi:type="string">input</item>
                    <item name="source" xsi:type="string">helloworld</item>
                    <item name="validation" xsi:type="array">
                        <item name="required-entry" xsi:type="boolean">true</item>
                    </item>
                </item>
            </argument>
        </field>
        <field name="content">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="label" xsi:type="string">Content:</item>
                    <item name="visible" xsi:type="boolean">true</item>
                    <item name="dataType" xsi:type="string">textarea</item>
                    <item name="formElement" xsi:type="string">textarea</item>
                    <item name="source" xsi:type="string">helloworld</item>
                </item>
            </argument>
        </field>        
     </fieldset>
 </form>
Author: Qaisar Satti
Category: Magento 2
Last Modified: February 9, 2018


Magento 2 create admin controller

Today we discuss how in magento 2 create admin controller. This tutorial include the basic structure of admin controller and how to execute admin controller. Now we start with our example.

For the custom admin controller first create the routes.xml file in following directory.

QaisarSatti/HelloWorld/etc/adminhtml/

<?xml version="1.0"?>
<!--/**
    * Hello World
    *
    * @category    QaisarSatti
    * @package     QaisarSatti_HelloWorld
    * @author      Muhammad Qaisar Satti
    * @Email       [email protected]
    *
    */ -->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd">
    <router id="admin">
        <route id="helloworld" frontName="helloworld">
            <module name="QaisarSatti_HelloWorld" before="Magento_Backend" />
        </route>
    </router>
</config>

Now create the admin controller. Index.php in following directory

QaisarSatti\HelloWorld\Controller\Adminhtml\Index

<?php
/**
    * Hello World
    *
    * @category    QaisarSatti
    * @package     QaisarSatti_HelloWorld
    * @author      Muhammad Qaisar Satti
    * @Email       [email protected]
    *
    */

namespace QaisarSatti\HelloWorld\Controller\Adminhtml\Index;

class Index extends \Magento\Backend\App\Action
{
   
    protected $resultPageFactory;

   
    public function __construct(
        \Magento\Backend\App\Action\Context $context,
        \Magento\Framework\Registry $coreRegistry,
        \Magento\Framework\View\Result\PageFactory $resultPageFactory
    ) {
        $this->resultPageFactory = $resultPageFactory;
        parent::__construct($context, $coreRegistry);
    }

   
    public function execute()
    {

        echo "My admin controller"; exit;
       

    }
   

 
    protected function _isAllowed()
    {
        return true;
    }
}

Note: This is basic example how to create custom admin controller

Author: Qaisar Satti
Category: Magento 2
Last Modified: February 8, 2018


Magento 2 sort collection by given ids

Today we discuss how in Magento 2 sort collection by give ids. Sometime we need to get product collection by given ids form example random ids 5,4,13. We take the example of product collection and filter it by give ids. You can use this on any kind of collection like order collection, category collection and any custom collection too. So here is our example.

protected $_productCollectionFactory;
public function __construct(
        \Magento\Catalog\Model\ResourceModel\Product\CollectionFactory $productFactory
    ) {
         $this->_productCollectionFactory = $productFactory;
    }
    public function getProductCollection()
    {
      $productIds=array(9,21,5,3);
        $productCollection = $this->_productCollectionFactory->create();
      $productCollection->getSelect()->order(new \Zend_Db_Expr('FIELD(at_status_default.entity_id,' . implode(',', $productIds).')'));
      return $productCollection;
     
     }

Note: You can sort any collection following this example.

Author: Qaisar Satti
Category: Magento 2
Last Modified: February 7, 2018


Pages:12345678