Hikmadh Commerce| Ecommerce Development Consulting | Magento Development and Consulting Service

The form (uiComponent) of the backend and the CRUD in magento2 admin

 

In uiComponent listing (grid) to our module in the backend of magento2! We will now see how to add a form to Add / Modify / Delete (CRUD) our objects with in this module. For that, we will start from the files of our previous tutorial.

Display the form via the magento2 Action

To create our Form, we will first create the newAction action in our controller like this: (/Hikmadh/Mymodule/Controller/Adminhtml/Contact/NewAction.php)

				
					<?php
namespace Hikmadh\Mymodule\Controller\Adminhtml\Test;
use Magento\Backend\App\Action;
use Hikmadh\Mymodule\Model\Mymodel as Mymodel;

class NewAction extends \Magento\Backend\App\Action
{
    /**
     * Edit A Contact Page
     *
     * @return \Magento\Backend\Model\View\Result\Page|\Magento\Backend\Model\View\Result\Redirect
     * @SuppressWarnings(PHPMD.NPathComplexity)
     */
    public function execute()
    {
        $this->_view->loadLayout();
        $this->_view->renderLayout();

        $contactDatas = $this->getRequest()->getParam('mymodel');
        if(is_array($mymodelDatas)) {
            $mymodel = $this->_objectManager->create(Mymodel::class);
            $mymodel->setData($mymodelDatas)->save();
            $resultRedirect = $this->resultRedirectFactory->create();
            return $resultRedirect->setPath('*/*/index');
        }
    }
}

				
			

We load and then display the layout that will contain the form. We check if we receive the parameter “contact” (if the form is sent), if yes then we save the contact in the database . Logically, we will now create the layout (/Hikmadh/Mymodule/view/adminhtml/layout/mymodel_test_newaction.xml):

				
					<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <update handle="contacts_test_edit"/>
    <body/>
</page>
				
			

In this layout, we just tell him to look for our layout contacts_text_edit. We create the layout file for editing (/Hikmadh/Mymodule/view/adminhtml/layout/mymodel_test_edit.xml):

				
					<?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"/>
    <update handle="editor"/>
    <body>
       <referenceContainer name="content">
            <uiComponent name="hikmadh_mymodule_form"/>
        </referenceContainer>
    </body<
</page>
				
			

Creating the file uiComponent for creation our form in magento2

Here it is said to load a uiComponent named “hikmadh_mymodel_form”, ( remember we did the same for the grid in the previous tutorial). We will therefore create the form in this uiComponent form.

So let’s create our uiComponent file for our form ( app/code/Hikmadh/Mymodule/view/adminhtml/ui_component/hikmadh_mymodel_form.xml ) :

				
					<?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">hikmadh_mymodel_form.mymodel_form_data_source<item>
            <item name="deps" xsi:type="string">hikmadh_mymodel_form.mymodel_form_data_source<item>
        <item>
        <item name="label" xsi:type="string" translate="true">Sample Form<item>
        <item name="layout" xsi:type="array">
            <item name="type" xsi:type="string">tabs<item>
        <item>

        <item name="buttons" xsi:type="array">
            <item name="back" xsi:type="string">Hikmadh\Mymodule\Block\Adminhtml\Mymodel\Edit\BackButton<item>
            <item name="delete" xsi:type="string">Hikmadh\Mymodule\Block\Adminhtml\Mymodel\Edit\DeleteButton<item>
            <item name="reset" xsi:type="string">Hikmadh\Mymodule\Block\Adminhtml\Mymodel\Edit\ResetButton<item>
            <item name="save" xsi:type="string">Hikmadh\Mymodule\Block\Adminhtml\Mymodel\Edit\SaveButton<item>
        <item>
    <argument>

    <dataSource name="mymodel_form_data_source">
        <argument name="dataProvider" xsi:type="configurableObject">
            <argument name="class" xsi:type="string">Hikmadh\Mymodule\Model\Mymodel\DataProvider<argument>
            <argument name="name" xsi:type="string">contacts_form_data_source<argument>
            <argument name="primaryFieldName" xsi:type="string">hikmadh_contacts_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="Mymodel">
        <argument name="data" xsi:type="array">
            <item name="config" xsi:type="array">
                <item name="label" xsi:type="string" translate="true">Sample Fieldset<item>
            <item>
        <argument>

        
        <field name="hikmadh_mymodel_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">Mymodel<item>
                <item>
            <argument>
        <field>

        
        <field name="name">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="label" xsi:type="string">Name<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">Mymodel<item>
                <item>
            <argument>
        <field>


        
        <field name="email">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="label" xsi:type="string">Email<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">Mymodel<item>
                <item>
            <argument>
        <field>

    <fieldset>
<form>
				
			

Here the file looks complicated but you have to break it down.Do not worry it’s not that complicated. The file uiComponent for a form is composed of several tags:

  1. argument: The base of the file, which allows to configure the data_source to use, the label, and the display of buttons
    • data: allows to make the links with the dataSource, pay attention to well define your “file name paths.” of the datasource
    • buttons: if you have come up to it is that you know how to read an xml normally but we will still specify it is here that the buttons are added. For each button a name and a class to be used are delined. We’ll come back to it later.
  2. dataSource: The configuration of the dataSource itself, the links between the database and our form. The datasource defines the links between the database and your formualire, here it is given the name “mymodel_form_data_source” and the class “Hikmadh\Mymodule\Model\Mymodel\DataProvider”. We define that the id in our table will be “hikmadh_mymodel_id” but that it will be renamed “id” in our form.
  3. fieldset: The fieldset is used to define the fields of your form.
    • field: represents a field of our form, they can be of several types that I invite you to search on the documentation of magento2. Here we used only text fields to facilitate our work. We define the same as the cahmps for the id will be invisible.

The DataSource of our magento2 form

The datasource of our magento2 form takes here our class “Hikmadh\Mymodule\Model\Mymodel\DataProvider” so we will create it.

So create the app/code/Hikmadh/Mymodule/Model/Mymodel/DataProvider.php file like this:

				
					<?php
namespace Hikmadh\Mymodule\Model\Mymodel;
use Hikmadh\Mymodule\Model\ResourceModel\Mymodel\CollectionFactory;
class DataProvider extends \Magento\Ui\DataProvider\AbstractDataProvider
{
    /**
     * @param string $name
     * @param string $primaryFieldName
     * @param string $requestFieldName
     * @param CollectionFactory $contactCollectionFactory
     * @param array $meta
     * @param array $data
     */
    public function __construct(
        $name,
        $primaryFieldName,
        $requestFieldName,
        CollectionFactory $contactCollectionFactory,
        array $meta = [],
        array $data = []
    ) {
        $this->collection = $mymodelCollectionFactory->create();
        parent::__construct($name, $primaryFieldName, $requestFieldName, $meta, $data);
    }

    public function getData()
    {
        if (isset($this->loadedData)) {
            return $this->loadedData;
        }

        $items = $this->collection->getItems();
        $this->loadedData = array();
        /** @var Customer $customer */
        foreach ($items as $mymodel) {
            // notre fieldset s'apelle "mymodel" d'ou ce tableau pour que magento puisse retrouver ses datas :
            $this->loadedData[$mymodel->getId()]['mymodel'] = $mymodel->getData();
        }


        return $this->loadedData;

    }
}
				
			

It is this file that allows our fields to be automatically mapped to the database. The so-called “dataBinding”. Here we called our fieldset “mymodel”, so we pass our Mymodel object in the loadedData array that we return.

Configuring our form buttons

Under magento2, in the forms, we define classes for buttons like what we did in our uiComponent:

				
					<item name="buttons" xsi:type="array">
           <item name="back" xsi:type="string">Hikmadh\Mymodule\Block\Adminhtml\Contact\Edit\BackButton
            <item name="delete" xsi:type="string">Hikmadh\Mymodule\Block\Adminhtml\Contact\Edit\DeleteButton
           <item name="reset" xsi:type="string">Hikmadh\Mymodule\Block\Adminhtml\Contact\Edit\ResetButton
            <item name="save" xsi:type="string">Hikmadh\Mymodule\Block\Adminhtml\Contact\Edit\SaveButton
        </item>
		try' );
				
			

We will create our files:

Create a GenericButton:

The GenericButton is the element that allows other buttons to exist. This is the base that extends the other buttons. app/code/Hikmadh/Mymodule/Block/Adminhtml/Contact/Edit/GenericButton.php

				
					<?php
namespace Hikmadh\Mymodule\Block\Adminhtml\Contact\Edit;

use Magento\Search\Controller\RegistryConstants;

/**
 * Class GenericButton
 */
class GenericButton
{
    /**
     * Url Builder
     *
     * @var \Magento\Framework\UrlInterface
     */
    protected $urlBuilder;

    /**
     * Registry
     *
     * @var \Magento\Framework\Registry
     */
    protected $registry;

    /**
     * Constructor
     *
     * @param \Magento\Backend\Block\Widget\Context $context
     * @param \Magento\Framework\Registry $registry
     */
    public function __construct(
        \Magento\Backend\Block\Widget\Context $context,
        \Magento\Framework\Registry $registry
    ) {
        $this->urlBuilder = $context->getUrlBuilder();
        $this->registry = $registry;
    }

    /**
     * Return the synonyms group Id.
     *
     * @return int|null
     */
    public function getId()
    {
        $mymodel = $this->registry->registry('mymodel');
        return $mymodel ? $mymodel->getId() : null;
    }

    /**
     * Generate url by route and parameters
     *
     * @param   string $route
     * @param   array $params
     * @return  string
     */
    public function getUrl($route = '', $params = [])
    {
        return $this->urlBuilder->getUrl($route, $params);
    }
}
				
			

Create a button to save our magento2 form

Create the file app/code/Hikmadh/Mymodule/Block/Adminhtml/Mymodel/Edit/BackButton.php In which you just configure the label of the button, the associated event and the form-role that automatically triggers events js for magento2.

				
					<?php
namespace Hikmadh\Mymodule\Block\Adminhtml\Contact\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('*/*/');
    }
}
				
			
Create a button to delete an object using our form



Then create the file to delete an item from our formular App/code/Hikmadh/Mymodule/Block/Adminhtml/Mymodel/Edit/DeleteButton.php Here it is more or less pariel but for the suppression:

				
					<?php
namespace Hikmadh\Mymodule\Block\Adminhtml\Contact\Edit;

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

/**
 * Class DeleteButton
 */
class DeleteButton extends GenericButton implements ButtonProviderInterface
{
    /**
     * @return array
     */
    public function getButtonData()
    {
        $data = [];
        if ($this->getId()) {
            $data = [
                'label' => __('Delete Contact'),
                'class' => 'delete',
                'on_click' => 'deleteConfirm(\''
                    . __('Are you sure you want to delete this contact ?')
                    . '\', \'' . $this->getDeleteUrl() . '\')',
                'sort_order' => 20,
            ];
        }
        return $data;
    }

    /**
     * @return string
     */
    public function getDeleteUrl()
    {
        return $this->getUrl('*/*/delete', ['hikmadh_mymodel_id' => $this->getId()]);
    }
}
				
			

Create a reset button to reset our magento2 form

app/code/Hikmadh/Mymodule/Block/Adminhtml/Contact/Edit/ResetButton.php

				
					<?php
namespace Hikmadh\Mymodule\Block\Adminhtml\Mymodel\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
        ];
    }
}
				
			

Create a reset button to save our form

app/code/Hikmadh/Mymodule/Block/Adminhtml/Contact/Edit/SaveButton.php

				
					<?php
namespace Hikmadh\Mymodule\Block\Adminhtml\Contact\Edit;

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

/**
 * Class SaveButton
 */
class SaveButton extends GenericButton implements ButtonProviderInterface
{
    /**
     * @return array
     */
    public function getButtonData()
    {
        return [
            'label' => __('Save Contact'),
            'class' => 'save primary',
            'data_attribute' => [
                'mage-init' => ['button' => ['event' => 'save']],
                'form-role' => 'save',
            ],
            'sort_order' => 90,
        ];
    }
}
				
			

And here are !! Our buttons are created and theoretically everything should work 🙂

Create our delete action

We create our delete action to remove an object from the magento grid like this:

				
					<?php
namespace Hikmadh\Mymodule\Controller\Adminhtml\Test;
use Hikmadh\Mymodule\Model\Mymodel as Mymodel;
use Magento\Backend\App\Action;

class Delete extends \Magento\Backend\App\Action
{
    public function execute()
    {
        $id = $this->getRequest()->getParam('id');

        if (!($contact = $this->_objectManager->create(Contact::class)->load($id))) {
            $this->messageManager->addError(__('Unable to proceed. Please, try again.'));
            $resultRedirect = $this->resultRedirectFactory->create();
            return $resultRedirect->setPath('*/*/index', array('_current' => true));
        }
        try{
            $contact->delete();
            $this->messageManager->addSuccess(__('Your contact has been deleted !'));
        } catch (Exception $e) {
            $this->messageManager->addError(__('Error while trying to delete contact: '));
            $resultRedirect = $this->resultRedirectFactory->create();
            return $resultRedirect->setPath('*/*/index', array('_current' => true));
        }

        $resultRedirect = $this->resultRedirectFactory->create();
        return $resultRedirect->setPath('*/*/index', array('_current' => true));
    }
}
 );