Today, we will teach you how to create UI Form and UI Grid in Magento 2. First of all, we will explain to you UI Form and then UI Grid. In the previous blog, we saw how to perform CRUD operations with the custom module in Magento 2. The UI Component is designed to have a simple and scalable user interface.
It makes it possible to link visual UI components to the associated user data process. For admin in Magento 2 UI components are the most important element. The Form component is a group of fields divided into tabs and fieldsets. The Listing UI Grid component is implements grids, lists, and tiles with filtering, pagination, sorting and lots of other features.
We need to create a contact form with the Name, Email, Phone No, Message, and table name is dolphin_mymodule_contact. So first of all create InstallSchema/UpgradeSchema and Model, Resource Model for this dolphin_mymodule_contact table.
<?xml version="1.0"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd"> <router id="admin"> <route id="mymodule" frontName="mymodule"> <module name="Dolphin_MyModule"/> </route> </router> </config>
Step 2: Create a controller file Edit.php in app/code/Dolphin/MyModule/Controller/Adminhtml/Contact folder.
<?php namespace Dolphin\MyModule\Controller\Adminhtml\Contact; class Edit extends \Magento\Backend\App\Action { protected $resultPageFactory; public function __construct( \Magento\Backend\App\Action\Context $context, \Magento\Framework\View\Result\PageFactory $resultPageFactory ) { parent::__construct($context); $this->resultPageFactory = $resultPageFactory; } public function execute() { $resultPage = $this->resultPageFactory->create(); $resultPage->getConfig()->getTitle()->prepend(__('Edit Contacts')); return $resultPage; } }
Step 3: Create a layout file mymodule_contact_edit.xml in app/code/Dolphin/MyModule/view/adminhtml/layout folder.
<?xml version="1.0"?> <page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"> <update handle="styles"/> <body> <referenceContainer name="content"> <uiComponent name="contact_form"/> </referenceContainer> </body> </page>
Step 4: Create UI form file contact_form.xml in app/code/Dolphin/MyModule/view/adminhtml/ui_component folder.
<?xml version="1.0" encoding="UTF-8"?> <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">contact_form.contact_form_data_source</item> <item name="deps" xsi:type="string">contact_form.contact_form_data_source</item> </item> <item name="label" xsi:type="string" translate="true">General Information</item> <item name="config" xsi:type="array"> <item name="dataScope" xsi:type="string">data</item> <item name="namespace" xsi:type="string">contact_form</item> </item> <item name="spinner" xsi:type="string">general_information</item> <item name="template" xsi:type="string">templates/form/collapsible</item> </argument> <dataSource name="contact_form_data_source"> <argument name="dataProvider" xsi:type="configurableObject"> <argument name="class" xsi:type="string">Dolphin\MyModule\Model\DataProvider</argument> <argument name="name" xsi:type="string">contact_form_data_source</argument> <argument name="primaryFieldName" xsi:type="string">id</argument> <argument name="requestFieldName" xsi:type="string">id</argument> </argument> <argument name="data" xsi:type="array"> <item name="js_config" xsi:type="array"> <item name="component" xsi:type="string">Magento_Ui/js/form/provider</item> </item> </argument> </dataSource> <fieldset name="general_information"> <argument name="data" xsi:type="array"> <item name="config" xsi:type="array"> <item name="collapsible" xsi:type="boolean">false</item> <item name="label" xsi:type="string" translate="true">General Information</item> <item name="sortOrder" xsi:type="number">10</item> </item> </argument> <field name="name"> <argument name="data" xsi:type="array"> <item name="config" xsi:type="array"> <item name="dataType" xsi:type="string">text</item> <item name="label" xsi:type="string" translate="true">Name</item> <item name="formElement" xsi:type="string">input</item> <item name="source" xsi:type="string">name</item> <item name="dataScope" xsi:type="string">name</item> <item name="validation" xsi:type="array"> <item name="required-entry" xsi:type="boolean">true</item> </item> </item> </argument> </field> <field name="email"> <argument name="data" xsi:type="array"> <item name="config" xsi:type="array"> <item name="dataType" xsi:type="string">text</item> <item name="label" xsi:type="string" translate="true">Email</item> <item name="formElement" xsi:type="string">input</item> <item name="source" xsi:type="string">email</item> <item name="dataScope" xsi:type="string">email</item> </item> </argument> </field> <field name="phone_no"> <argument name="data" xsi:type="array"> <item name="config" xsi:type="array"> <item name="dataType" xsi:type="string">text</item> <item name="label" xsi:type="string" translate="true">Phone Number</item> <item name="formElement" xsi:type="string">input</item> <item name="source" xsi:type="string">phone_no</item> <item name="dataScope" xsi:type="string">phone_no</item> </item> </argument> </field> <field name="message"> <argument name="data" xsi:type="array"> <item name="config" xsi:type="array"> <item name="dataType" xsi:type="string">text</item> <item name="label" xsi:type="string" translate="true">Message</item> <item name="formElement" xsi:type="string">input</item> <item name="source" xsi:type="string">message</item> <item name="dataScope" xsi:type="string">message</item> </item> </argument> </field> </fieldset> </form>
If you need to add button in UI form then you can see the tutorial on how to add Buttons into Ui Component Form Magento 2.
Step 5: Create DataProvider.php file in app/code/Dolphin/MyModule/Model folder.
<?php namespace Dolphin\MyModule\Model; use Dolphin\MyModule\Model\ResourceModel\Contact\CollectionFactory; class DataProvider extends \Magento\Ui\DataProvider\AbstractDataProvider { protected $loadedData; public function __construct( $name, $primaryFieldName, $requestFieldName, CollectionFactory $collectionFactory, array $meta = [], array $data = [] ) { $this->collection = $collectionFactory->create(); parent::__construct($name, $primaryFieldName, $requestFieldName, $meta, $data); } public function getData() { if (isset($this->loadedData)) { return $this->loadedData; } $items = $this->collection->getItems(); foreach ($items as $item) { $this->loadedData[$item->getId()] = $item->getData(); } return $this->loadedData; } }
If you want to display values in this form from to database then you need to create ResourceModel and apply code in getData() function in DataProvider.php file. It’s already mentioned a code in this file.
Let’s start with the UI Grid.
Step 1: Create a controller file Index.php in app/code/Dolphin/MyModule/Controller/Adminhtml/Contact folder.
<?php namespace Dolphin\MyModule\Controller\Adminhtml\Contact; use Magento\Backend\App\Action\Context; use Magento\Framework\View\Result\PageFactory; class Index extends \Magento\Backend\App\Action { const ADMIN_RESOURCE = 'Dolphin_MyModule::Contact'; protected $resultPageFactory; public function __construct( \Magento\Framework\App\Action\Context $context, \Magento\Framework\View\Result\PageFactory $resultPageFactory ){ parent::__construct($context); $this->resultPageFactory = $resultPageFactory; } public function execute() { $resultPage = $this->resultPageFactory->create(); $resultPage->setActiveMenu('Dolphin_MyModule::Contact'); $resultPage->addBreadcrumb(__('Contact Data'), __('Contact Data')); $resultPage->addBreadcrumb(__('Contact Data'), __('Contact Data')); $resultPage->getConfig()->getTitle()->prepend(__('Contact Data')); return $resultPage; } }
Step 2: Create a layout file mymodule_contact_index.xml in app/code/Dolphin/MyModule/view/adminhtml/layout folder.
<?xml version="1.0"?> <page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"> <body> <referenceContainer name="content"> <uiComponent name="contact_listing"/> </referenceContainer> </body> </page>
Step 3: Create a grid listing file contact_listing.xml in app/code/Dolphin/MyModule/view/adminhtml/ui_component folder.
<?xml version="1.0"?> <listing xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Ui/etc/ui_configuration.xsd"> <argument name="data" xsi:type="array"> <item name="js_config" xsi:type="array"> <item name="provider" xsi:type="string">contact_listing.contact_listing_data_source</item> <item name="deps" xsi:type="string">contact_listing.contact_listing_data_source</item> </item> <item name="spinner" xsi:type="string">contact_listing_columns</item> <item name="buttons" xsi:type="array"> <item name="add" xsi:type="array"> <item name="name" xsi:type="string">add</item> <item name="label" xsi:type="string" translate="true">Add New</item> <item name="class" xsi:type="string">primary</item> <item name="url" xsi:type="string">*/*/new</item> </item> </item> </argument> <dataSource name="contact_listing_data_source"> <argument name="dataProvider" xsi:type="configurableObject"> <argument name="class" xsi:type="string">Magento\Framework\View\Element\UiComponent\DataProvider\DataProvider</argument> <argument name="name" xsi:type="string">contact_listing_data_source</argument> <argument name="primaryFieldName" xsi:type="string">id</argument> <argument name="requestFieldName" xsi:type="string">id</argument> <argument name="data" xsi:type="array"> <item name="config" xsi:type="array"> <item name="update_url" xsi:type="url" path="mui/index/render"/> </item> </argument> </argument> <argument name="data" xsi:type="array"> <item name="js_config" xsi:type="array"> <item name="component" xsi:type="string">Magento_Ui/js/grid/provider</item> </item> </argument> </dataSource> <container name="listing_top"> <argument name="data" xsi:type="array"> <item name="config" xsi:type="array"> <item name="template" xsi:type="string">ui/grid/toolbar</item> </item> </argument> <bookmark name="bookmarks"> <argument name="data" xsi:type="array"> <item name="config" xsi:type="array"> <item name="component" xsi:type="string">Magento_Ui/js/grid/controls/bookmarks/bookmarks</item> <item name="displayArea" xsi:type="string">dataGridActions</item> <item name="storageConfig" xsi:type="array"> <item name="saveUrl" xsi:type="url" path="mui/bookmark/save"/> <item name="deleteUrl" xsi:type="url" path="mui/bookmark/delete"/> <item name="namespace" xsi:type="string">contact_listing</item> </item> </item> </argument> </bookmark> <container name="columns_controls"> <argument name="data" xsi:type="array"> <item name="config" xsi:type="array"> <item name="columnsData" xsi:type="array"> <item name="provider" xsi:type="string">contact_listing.contact_listing.contact_listing_columns</item> </item> <item name="component" xsi:type="string">Magento_Ui/js/grid/controls/columns</item> <item name="displayArea" xsi:type="string">dataGridActions</item> </item> </argument> </container> <filters name="listing_filters"> <argument name="data" xsi:type="array"> <item name="config" xsi:type="array"> <item name="displayArea" xsi:type="string">dataGridFilters</item> <item name="dataScope" xsi:type="string">filters</item> <item name="storageConfig" xsi:type="array"> <item name="provider" xsi:type="string">contact_listing.contact_listing.listing_top.bookmarks</item> <item name="namespace" xsi:type="string">current.filters</item> </item> <item name="childDefaults" xsi:type="array"> <item name="provider" xsi:type="string">contact_listing.contact_listing.listing_top.listing_filters</item> <item name="imports" xsi:type="array"> <item name="visible" xsi:type="string">contact_listing.contact_listing.listing_top.bookmarks:current.columns.${ $.index }.visible</item> </item> </item> </item> </argument> <filterRange name="id"> <argument name="data" xsi:type="array"> <item name="config" xsi:type="array"> <item name="dataScope" xsi:type="string">id</item> <item name="label" xsi:type="string" translate="true">ID</item> <item name="childDefaults" xsi:type="array"> <item name="provider" xsi:type="string">contact_listing.contact_listing.listing_top.listing_filters</item> </item> </item> </argument> <filterInput name="from"> <argument name="data" xsi:type="array"> <item name="config" xsi:type="array"> <item name="dataScope" xsi:type="string">from</item> <item name="label" xsi:type="string" translate="true">from</item> <item name="placeholder" xsi:type="string" translate="true">From</item> </item> </argument> </filterInput> <filterInput name="to"> <argument name="data" xsi:type="array"> <item name="config" xsi:type="array"> <item name="dataScope" xsi:type="string">to</item> <item name="label" xsi:type="string" translate="true">to</item> <item name="placeholder" xsi:type="string" translate="true">To</item> </item> </argument> </filterInput> </filterRange> <filterInput name="name"> <argument name="data" xsi:type="array"> <item name="config" xsi:type="array"> <item name="dataScope" xsi:type="string">name</item> <item name="label" xsi:type="string" translate="true">Name</item> </item> </argument> </filterInput> <filterInput name="status"> <argument name="data" xsi:type="array"> <item name="config" xsi:type="array"> <item name="dataScope" xsi:type="string">status</item> <item name="label" xsi:type="string" translate="true">Status</item> </item> </argument> </filterInput> </filters> <massaction name="listing_massaction"> <argument name="data" xsi:type="array"> <item name="config" xsi:type="array"> <item name="selectProvider" xsi:type="string">contact_listing.contact_listing.contact_listing_columns.ids</item> <item name="component" xsi:type="string">Magento_Ui/js/grid/tree-massactions</item> <item name="indexField" xsi:type="string">id</item> </item> </argument> <action name="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="mymodule/contact/massDelete"/> </item> </argument> </action> <action name="status"> <argument name="data" xsi:type="array"> <item name="config" xsi:type="array"> <item name="type" xsi:type="string">status</item> <item name="label" xsi:type="string" translate="true">Change status</item> </item> </argument> <argument name="actions" xsi:type="array"> <item name="0" xsi:type="array"> <item name="type" xsi:type="string">enable</item> <item name="label" xsi:type="string" translate="true">Enable</item> <item name="url" xsi:type="url" path="mymodule/contact/massStatus"> <param name="status">1</param> </item> </item> <item name="1" xsi:type="array"> <item name="type" xsi:type="string">disable</item> <item name="label" xsi:type="string" translate="true">Disable</item> <item name="url" xsi:type="url" path="mymodule/contact/massStatus"> <param name="status">0</param> </item> </item> </argument> </action> </massaction> <paging name="listing_paging"> <argument name="data" xsi:type="array"> <item name="config" xsi:type="array"> <item name="storageConfig" xsi:type="array"> <item name="provider" xsi:type="string">contact_listing.contact_listing.listing_top.bookmarks</item> <item name="namespace" xsi:type="string">current.paging</item> </item> <item name="selectProvider" xsi:type="string">contact_listing.contact_listing.contact_listing_columns.ids</item> <item name="displayArea" xsi:type="string">bottom</item> </item> </argument> </paging> </container> <columns name="contact_listing_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">contact_listing.contact_listing.listing_top.bookmarks</item> <item name="namespace" xsi:type="string">current</item> </item> <item name="childDefaults" xsi:type="array"> <item name="fieldAction" xsi:type="array"> <item name="provider" xsi:type="string">contact_listing.contact_listing.contact_listing_columns.actions</item> <item name="target" xsi:type="string">applyAction</item> <item name="params" xsi:type="array"> <item name="0" xsi:type="string">edit</item> <item name="1" xsi:type="string">${ $.$data.rowIndex }</item> </item> </item> <item name="storageConfig" xsi:type="array"> <item name="provider" xsi:type="string">contact_listing.contact_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="indexField" xsi:type="string">id</item> <item name="sortOrder" xsi:type="number">0</item> </item> </argument> </selectionsColumn> <column name="id"> <argument name="data" xsi:type="array"> <item name="config" xsi:type="array"> <item name="filter" xsi:type="string">text</item> <item name="component" xsi:type="string">Magento_Ui/js/grid/columns/column</item> <item name="dataType" xsi:type="string">text</item> <item name="label" xsi:type="string" translate="true">Id</item> <item name="sortOrder" xsi:type="number">10</item> </item> </argument> </column> <column name="name"> <argument name="data" xsi:type="array"> <item name="config" xsi:type="array"> <item name="filter" xsi:type="string">text</item> <item name="component" xsi:type="string">Magento_Ui/js/grid/columns/column</item> <item name="dataType" xsi:type="string">text</item> <item name="label" xsi:type="string" translate="true">Name</item> <item name="sortOrder" xsi:type="number">20</item> </item> </argument> </column> <column name="email"> <argument name="data" xsi:type="array"> <item name="config" xsi:type="array"> <item name="filter" xsi:type="string">text</item> <item name="component" xsi:type="string">Magento_Ui/js/grid/columns/column</item> <item name="dataType" xsi:type="string">text</item> <item name="label" xsi:type="string" translate="true">Email</item> <item name="sortOrder" xsi:type="number">30</item> </item> </argument> </column> <column name="message"> <argument name="data" xsi:type="array"> <item name="config" xsi:type="array"> <item name="filter" xsi:type="string">text</item> <item name="component" xsi:type="string">Magento_Ui/js/grid/columns/column</item> <item name="dataType" xsi:type="string">text</item> <item name="label" xsi:type="string" translate="true">Message</item> <item name="sortOrder" xsi:type="number">40</item> </item> </argument> </column> <column name="status"> <argument name="data" xsi:type="array"> <item name="options" xsi:type="object">Dolphin\MyModule\Model\Contact\Source\Status</item> <item name="config" xsi:type="array"> <item name="filter" xsi:type="string">select</item> <item name="component" xsi:type="string">Magento_Ui/js/grid/columns/select</item> <item name="editor" xsi:type="string">select</item> <item name="dataType" xsi:type="string">select</item> <item name="label" xsi:type="string" translate="true">Status</item> <item name="sortOrder" xsi:type="number">50</item> </item> </argument> </column> <actionsColumn name="actions" class="Dolphin\MyModule\Ui\Component\Listing\Column\ContactActions"> <argument name="data" xsi:type="array"> <item name="config" xsi:type="array"> <item name="indexField" xsi:type="string">id</item> <item name="sortOrder" xsi:type="number">200</item> </item> </argument> </actionsColumn> </columns> </listing>
Step 4: Create a grid listing file di.xml in app/code/Dolphin/MyModule/etc folder.
<?xml version="1.0"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"> <virtualType name="Dolphin\MyModule\Model\ResourceModel\Contact\Grid\Collection"> <arguments> <argument name="mainTable" xsi:type="string">dolphin_mymodule_contact</argument> <argument name="resourceModel" xsi:type="string">Dolphin\MyModule\Model\ResourceModel\Contact</argument> </arguments> </virtualType> <type name="Magento\Framework\View\Element\UiComponent\DataProvider\CollectionFactory"> <arguments> <argument name="collections" xsi:type="array"> <item name="entity_listing_data_source1" xsi:type="string">Dolphin\MyModule\Model\ResourceModel\Contact\Grid\Collection</item> </argument> </arguments> </type> </config>
Step 5: Now, we need to create Status.php file in app/code/Dolphin/MyModule/Model/Contact/Source folder.
<?php namespace Dolphin\MyModule\Model\Contact\Source; class Status implements \Magento\Framework\Data\OptionSourceInterface { protected $contact; public function __construct( \Dolphin\MyModule\Model\Contact $contact ){ $this->contact = $contact; } public function toOptionArray() { $options[] = ['label' => '', 'value' => '']; $availableOptions = $this->getOptionArray(); foreach ($availableOptions as $key => $value) { $options[] = [ 'label' => $value, 'value' => $key, ]; } return $options; } public static function getOptionArray() { return [ 1 => __('Enabled'), 0 => __('Disabled') ]; } }
Step 6: Create ContactActions.php file in app/code/Dolphin/MyModule/Ui/Component/Listing/Column folder.
<?php namespace Dolphin\MyModule\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 Magento\Framework\UrlInterface; class ContactActions extends Column { const CONTACT_URL_PATH_EDIT = 'mymodule/contact/edit'; const CONTACT_URL_PATH_DELETE = 'mymodule/contact/delete'; protected $urlBuilder; private $editUrl; public function __construct( ContextInterface $context, UiComponentFactory $uiComponentFactory, UrlInterface $urlBuilder, array $components = [], array $data = [], $editUrl = self::CONTACT_URL_PATH_EDIT ) { $this->urlBuilder = $urlBuilder; $this->editUrl = $editUrl; parent::__construct($context, $uiComponentFactory, $components, $data); } public function prepareDataSource(array $dataSource) { if (isset($dataSource['data']['items'])) { foreach ($dataSource['data']['items'] as & $item) { $name = $this->getData('name'); if (isset($item['id'])) { $item[$name]['edit'] = [ 'href' => $this->urlBuilder->getUrl($this->editUrl, ['id' => $item['id']]), 'label' => __('Edit') ]; $item[$name]['delete'] = [ 'href' => $this->urlBuilder->getUrl(self::CONTACT_URL_PATH_DELETE, ['id' => $item['id']]), 'label' => __('Delete'), 'confirm' => [ 'title' => __('Delete "${ $.$data.name }"'), 'message' => __('Are you sure you wan\'t to delete a "${ $.$data.name }" record?') ] ]; } } } return $dataSource; } }
We hope our guide is very effective for you. If any questions, please feel free to leave a comment below. n the next tutorial, you will help with how to use System Configuration and Helpers in Magento 2.