Create UI Form in Magento 2
As we know starting from Magento 2, most of the new admin console is built on top of UI component. This is intended to combine HTML and JavaScript content, allowing the creation of new components with any form and function possible. In the previous post we created a simple grid with UI component and in this article we will continue to use it to create UI Form in Magento backend.
Here, we continue to use the simple module built in the previous post and build the create/edit message form in the backend.
1. Create admin controller
Create NewAction
Create file app\code\Magerubik\Simple\Controller\Adminhtml\Message\NewAction.php with below content.
<?php namespace Magerubik\Simple\Controller\Adminhtml\Message; class NewAction extends \Magento\Backend\App\Action { public function execute() { $this->_forward('edit'); } }
This controller will redirect to edit page.
Create Edit controller
Create file app\code\Magerubik\Simple\Controller\Adminhtml\Message\Edit.php with below content.
<?php namespace Magerubik\Simple\Controller\Adminhtml\Message; 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(__('Message')); return $resultPage; } }
2. Create Edit page Layout
Create file app\code\Magerubik\Simple\view\adminhtml\layout\simple_message_edit.xml with below content.
<?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="editor"/> <body> <referenceContainer name="content"> <uiComponent name="message_send_form"/> </referenceContainer> </body> </page>
3. Create Ui form
Create file app\code\Magerubik\Simple\view\adminhtml\ui_component\message_send_form.xml with below content.
<?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">message_send_form.message_send_form_data_source</item> <item name="deps" xsi:type="string">message_send_form.message_send_form_data_source</item> </item> <item name="label" xsi:type="string" translate="true">Send Message</item> <item name="config" xsi:type="array"> <item name="dataScope" xsi:type="string">data</item> <item name="namespace" xsi:type="string">message_send_form</item> </item> <item name="template" xsi:type="string">templates/form/collapsible</item> <item name="buttons" xsi:type="array"> <item name="back" xsi:type="array"> <item name="name" xsi:type="string">back</item> <item name="label" xsi:type="string" translate="true">Back</item> <item name="class" xsi:type="string">back</item> <item name="url" xsi:type="string">*/*/</item> </item> <item name="save" xsi:type="string">Magerubik\Simple\Block\Adminhtml\Button\Save</item> </item> </argument> <dataSource name="message_send_form_data_source"> <argument name="dataProvider" xsi:type="configurableObject"> <argument name="class" xsi:type="string">Magerubik\Simple\Model\DataProvider\MessageDataProvider</argument> <argument name="name" xsi:type="string">message_send_form_data_source</argument> <argument name="primaryFieldName" xsi:type="string">messages_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="*/message/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" translate="true"></item> <item name="collapsible" xsi:type="boolean">false</item> <item name="sortOrder" xsi:type="number">10</item> </item> </argument> <field name="messages_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="dataScope" xsi:type="string">messages_id</item> </item> </argument> </field> <field name="user_id"> <argument name="data" xsi:type="array"> <item name="config" xsi:type="array"> <item name="label" xsi:type="string" translate="true">user id</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="dataScope" xsi:type="string">user_id</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" translate="true">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="dataScope" xsi:type="string">title</item> <item name="validation" xsi:type="array"> <item name="required-entry" xsi:type="boolean">true</item> </item> </item> </argument> </field> <field name="description"> <argument name="data" xsi:type="array"> <item name="config" xsi:type="array"> <item name="label" xsi:type="string" translate="true">Message</item> <item name="visible" xsi:type="boolean">true</item> <item name="dataType" xsi:type="string">text</item> <item name="formElement" xsi:type="string">textarea</item> <item name="dataScope" xsi:type="string">description</item> <item name="validation" xsi:type="array"> <item name="required-entry" xsi:type="boolean">true</item> </item> </item> </argument> </field> </fieldset> </form>
Create Save button
Create two files file Save.php and Generic.php with below content then put its in same folder app\code\Magerubik\Simple\Block\Adminhtml\Button
<?php namespace Magerubik\Simple\Block\Adminhtml\Button; use Magento\Backend\Block\Widget\Context; use Magento\Cms\Api\PageRepositoryInterface; class Generic { protected $context; protected $pageRepository; public function __construct( Context $context, PageRepositoryInterface $pageRepository ) { $this->context = $context; $this->pageRepository = $pageRepository; } public function getUrl($route = '', $params = []) { return $this->context->getUrlBuilder()->getUrl($route, $params); } }
<?php namespace Magerubik\Simple\Block\Adminhtml\Button; use Magento\Framework\View\Element\UiComponent\Control\ButtonProviderInterface; use Magento\Ui\Component\Control\Container; class Save extends Generic implements ButtonProviderInterface { public function getButtonData() { return [ 'label' => __('Save'), 'class' => 'save primary', 'data_attribute' => [ 'mage-init' => [ 'buttonAdapter' => [ 'actions' => [ [ 'targetName' => 'message_send_form.message_send_form', 'actionName' => 'save', 'params' => [ false, ], ], ], ], ], ], ]; } }
4. Create model Data Provider
Create file app\code\Magerubik\Simple\Model\DataProvider\MessageDataProvider.php with below content.
<?php namespace Magerubik\Simple\Model\DataProvider; use Magerubik\Simple\Model\ResourceModel\Message\CollectionFactory; use Magerubik\Simple\Model\ImageProcessor; use Magento\Ui\DataProvider\AbstractDataProvider; use Magento\Framework\App\Request\DataPersistorInterface; class MessageDataProvider extends AbstractDataProvider { protected $loadedData; private $imageProcessor; public function __construct( $name, $primaryFieldName, $requestFieldName, CollectionFactory $collectionFactory, ImageProcessor $imageProcessor, DataPersistorInterface $dataPersistor, array $meta = [], array $data = [] ) { $this->collection = $collectionFactory->create(); $this->imageProcessor = $imageProcessor; $this->dataPersistor = $dataPersistor; parent::__construct($name, $primaryFieldName, $requestFieldName, $meta, $data); } public function getData() { $items = $this->collection->getItems(); foreach ($items as $model) { $this->loadedData[$model->getId()] = $model->getData(); } $data = $this->dataPersistor->get('mrsimple_message'); if (!empty($data)) { $model = $this->collection->getNewEmptyItem(); $model->setData($data); $this->loadedData[$model->getId()] = $model->getData(); $this->dataPersistor->clear('mrsimple_message'); } return $this->loadedData; } }
Now, go to backend flush cache then check result. If you can see like below screenshot everything is ok.
5. Create controller save data
Create file app\code\Magerubik\Simple\Controller\Adminhtml\Message\save.php with below content.
<?php namespace Magerubik\Simple\Controller\Adminhtml\Message; use Magento\Framework\Exception\LocalizedException; class Save extends \Magento\Backend\App\Action { protected $dataPersistor; public function __construct( \Magento\Backend\App\Action\Context $context, \Magento\Framework\App\Request\DataPersistorInterface $dataPersistor ) { $this->dataPersistor = $dataPersistor; parent::__construct($context); } public function execute() { $resultRedirect = $this->resultRedirectFactory->create(); $data = $this->getRequest()->getPostValue(); if ($data) { $id = $this->getRequest()->getParam('messages_id'); if($id){ $model = $this->_objectManager->create(\Magerubik\Simple\Model\Message::class)->load($id); if (!$model->getMessagesId()) { $this->messageManager->addErrorMessage(__('This message no longer exists.')); return $resultRedirect->setPath('*/*/'); } $model->setData($data)->setId($id); }else{ $model = $this->_objectManager->create(\Magerubik\Simple\Model\Message::class); $model->setData($data)->setId(NULL); } try { $model->save(); $this->messageManager->addSuccessMessage(__('You saved the message.')); $this->dataPersistor->clear('mrsimple_message'); return $resultRedirect->setPath('*/*/edit', ['id' => $model->getMessagesId()]); } catch (LocalizedException $e) { $this->messageManager->addErrorMessage($e->getMessage()); } catch (\Exception $e) { $this->messageManager->addExceptionMessage($e, __('Something went wrong while saving the message.')); } $this->dataPersistor->set('mrsimple_message', $data); return $resultRedirect->setPath('*/*/edit', ['id' => $this->getRequest()->getParam('messages_id')]); } return $resultRedirect->setPath('*/*/'); } }
Go to backend flush cache then check save function if see below the screenshot everything is ok.
Note: let’s get the user id from the customer table because we use it to get the user name in the grid.
OK, we’re done creating a simple UI from good luck with your practice. In the next post we will come back to this problem to add an image upload field. Contact us if you face any problems during the installation process.
You can download the demo code for this entire series from GitHub