Skip to content

Latest commit

 

History

History
745 lines (645 loc) · 26.7 KB

8.2.admin-ui-edit-form.md

File metadata and controls

745 lines (645 loc) · 26.7 KB

Magento2 Admin Ui component Edit Form

Required Files:

Previous All files from Doc:

  1. Admin Url and ACL
  2. Add Admin Menu
  3. Magento2 Admin Ui component Grid
  4. app/code/{Vendor}/{ModuleName}/Controller/Adminhtml/{ControllerFolderName}/{EditActionFileName}.php New
  5. app/code/{Vendor}/{ModuleName}/view/adminhtml/layout/{Admin_Route_Id}_{ControllerName_LowerCase}_{EditActionFileName_In_LowerCase}.xml (new)
  6. app/code/{Vendor}/{ModuleName}/view/adminhtml/ui_component/{Ui_Component_EDIT_FORM_Name_PREFIX}_form.xml.(new)
  7. app/code/{Vendor}/{ModuleName}/Ui/Model/{DataProviderClassName}.php (New)

Update the Listing Ui component. Add Edit /Delete link from Listing /Grid page.

Take a look at the Grid Action Class where edit page and Delete page Url is defined. See https://github.com/devamitbera/magento2-module-stucture/blob/master/8.1.admin-grid-using-ui.md#7ui_componentname_listing_name-file-action-class

app/code/{Vendor}/{ModuleName}/Ui/Listing/Columns/{UserDefinedClassForACtion}.php

4.Edit Action file:

Location: app/code/{Vendor}/{ModuleName}/Controller/Adminhtml/{ControllerFolderName}/{EditActionFileName}.php

====Code Format===

<?php
/**
 * Create edit page for Update data 
 */

namespace {Vendor}\{ModuleName}\Controller\Adminhtml\{ControllerFolderName};


class {EditActionFileName} extends  \Magento\Backend\App\Action
{

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

    /**
     * @var \Magento\Framework\View\Result\PageFactory
     */
    private $resultPageFactory;

    /**
     * @var \StackExchange\Example\Model\StudentFactory
     */
    private $yourModelVariableFactory;

    /**
     * 
     * Add Acl Resource id For Permission at admin section
     */
    const ADMIN_RESOURCE ="{EDIT_ACL_RESOURCE_ID}";
    
    public function __construct(
        \Magento\Backend\App\Action\Context $context,
        \{Vendor}\{ModuleName}\Model\{YourModel}Factory $yourModelVariableFactory,
        \Magento\Framework\View\Result\PageFactory $resultPageFactory,
        \Magento\Framework\Registry $registry  
    ) {
        $this->yourModelVariableFactory = $yourModelVariableFactory;  
        $this->resultPageFactory = $resultPageFactory;
        $this->registry = $registry;        
        parent::__construct($context);
    }

    public function execute() {
        
        /**
         * init Model using Model Factory
         */
        $yourModel= $this->yourModelVariableFactory->create();
        /**
         * for  update a row data, we need  primary  field value
         * which URL param "example_id" = Database example table "id" field
         */ 
        $id = $this->getRequest()->getParam('{Paramster_For_URL}');
        if($id){
            /**
             * Load a record data from data using model
             */
            $yourModel->load($id);
            /**
             * Redirect to listing page if a record does not exit at database 
             * with request parameter
             */
            if(!$yourModel->getId()){
               $resultRedirect =  $this->resultRedirectFactory->create();
               return $resultRedirect->setPath('*/*/listing');
            }
            
        }
        /**
         * Save Model Data to a registry variable for future purpose
         * Variable name is user defined
         */
        $this->registry->register('{Registry_Variable}',$yourModel);
        
        $resultPage =$this->resultPageFactory->create();
        $resultPage->getConfig()->setKeywords(__('Edit Page'));
        /**
         * Left menu Select
         */
        $resultPage->setActiveMenu('{MENU_ID}');
        /**
         * Set Page title
         */
        
        $resultPage->getConfig()->getTitle()->prepend('Example Module');
        $pageTitltPrefix = __('Edit Page for %1',
                $yourModel->getId()?$yourModel->getId(): __('New entry')
                );
        $resultPage->getConfig()->getTitle()->prepend($pageTitltPrefix);
        return $resultPage;
        
    }

}

User Defined

Example

<?php
/**
 * Create edit page for Update data 
 */

namespace StackExchange\Example\Controller\Adminhtml\Example;


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

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

    /**
     * @var \Magento\Framework\View\Result\PageFactory
     */
    private $resultPageFactory;

    /**
     * @var \StackExchange\Example\Model\StudentFactory
     */
    private $studentFactory;

    /**
     * 
     * Add Acl Resource id For Permission at admin section
     */
    const ADMIN_RESOURCE ="StackExchange_Example::example_edit";
    
    public function __construct(
        \Magento\Backend\App\Action\Context $context,
        \StackExchange\Example\Model\StudentFactory $studentFactory,
        \Magento\Framework\View\Result\PageFactory $resultPageFactory,
        \Magento\Framework\Registry $registry  
    ) {
        $this->studentFactory = $studentFactory;  
        $this->resultPageFactory = $resultPageFactory;
        $this->registry = $registry;        
        parent::__construct($context);
    }

    public function execute() {
        
        /**
         * init Model using Model Factory
         */
        $studentModel= $this->studentFactory->create();
        /**
         * for  update a row data, we need  primary  field value
         * which URL param "example_id" = Database example table "id" field
         */ 
        $id = $this->getRequest()->getParam('example_id');
        if($id){
            /**
             * Load a record data from data using model
             */
            $studentModel->load($id);
            /**
             * Redirect to listing page if a record does not exit at database 
             * with request parameter
             */
            if(!$studentModel->getId()){
               $resultRedirect =  $this->resultRedirectFactory->create();
               return $resultRedirect->setPath('*/*/listing');
            }
            
        }
        /**
         * Save Model Data to a registry variable for future purpose
         * Variable name is user defined
         */
        $this->registry->register('example',$studentModel);
        
        $resultPage =$this->resultPageFactory->create();
        $resultPage->getConfig()->setKeywords(__('Edit Page'));
        /**
         * Left menu Select
         */
        $resultPage->setActiveMenu('StackExchange_Example::menu');
        /**
         * Set Page title
         */
        
        $resultPage->getConfig()->getTitle()->prepend('Example Module');
        $pageTitltPrefix = __('Edit Page for %1',
                $studentModel->getId()?$studentModel->getName(): __('New entry')
                );
        $resultPage->getConfig()->getTitle()->prepend($pageTitltPrefix);
        return $resultPage;
        
    }

}

5.Create layout Xml file for Edit page

First you have to create layout file for edit page:

File location should be: app/code/{Vendor}/{ModuleName}/view/adminhtml/layout/{Admin_Route_Id}_{ControllerName_LowerCase}_{EditActionFileName_In_LowerCase}.xml

And this file, need to defined UI Component Edit Form name.

==== Code Format ====

<?xml version="1.0" encoding="UTF-8"?>
<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">
            <!--add UI component form File name-->
            <uiComponent name="{Ui_Component_EDIT_FORM_Name_PREFIX}_form"/>
        </referenceContainer>
    </body>
</page>  

User Defined:

  • Edit Form ui Component file name : define under <uiComponent></<uiComponent>. Format {Ui_Component_EDIT_FORM_Name_PREFIX}_form. Example example_ui_form i.e <uiComponent name="example_ui_form"/>.

Example

<?xml version="1.0" encoding="UTF-8"?>
<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">
            <!--add UI component form File name-->
            <uiComponent name="example_ui_form"/>
        </referenceContainer>
    </body>
</page>  

6. Ui Componen edit Form :

File Name Is Define at https://github.com/devamitbera/magento2-module-stucture/blob/master/8.2.admin-ui-edit-form.md#create-layout-xml-file-for-edit-page Under uiComponent tag

  • File Name and Location: app/code/{Vendor}/{ModuleName}/view/adminhtml/ui_component/{Ui_Component_EDIT_FORM_Name_PREFIX}_form.xml

==== CODE FORMAT===*

<?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">
            <!-- Data source provide Name with format 
             UIComponentFilename.UIComponentFilename_data_source
             -->            
                        
            <item name="provider" xsi:type="string">{Ui_Component_EDIT_FORM_Name_PREFIX}_form.{Data_Source_Prefix}_data_source</item>
        </item>
        <item name="label" xsi:type="string" translate="true">General Information</item>
        <item name="template" xsi:type="string">templates/form/collapsible</item>
    </argument>
    <!-- Mapping Data  with Ui component -->
    <settings>
        <namespace>{Ui_Component_EDIT_FORM_Name_PREFIX}_form</namespace>
        <dataScope>data</dataScope>
        <deps>
            <dep>{Ui_Component_EDIT_FORM_Name_PREFIX}_form.{Data_Source_Prefix}_data_source</dep>
        </deps>
    </settings>
    <!-- define Data source Name-->
    <dataSource name="{Data_Source_Prefix}_data_source">
        <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>
        <settings>
            <!--Save Url -->
            <submitUrl path="{Admin_Route_Id}/{ControllerName_LowerCase}/{Save_ActionFileName_In_LowerCase}"/>
        </settings>
        <!-- Declare Data provide Php class and it user defined Class-->
        <dataProvider class="{Edit_Form_PHP_DATA_PROVIDER_CLASAS}" 
                      name="{Data_Source_Prefix}_data_source">
            <settings>
                <!-- Url parameter name for getting  which corresponding to Db 
                table primary
                -->
                <requestFieldName>{RequestId_user_Defined_Name}</requestFieldName>
                <primaryFieldName>{Database_Table_Primary_key_Name}</primaryFieldName><!-- Db table primary key -->
            </settings>
        </dataProvider>
    </dataSource>
    <!-- Add Field to Edit Form -->
    <!-- FieldSet name is user Defined -->
    <fieldset name="{FieldSetName_1}">
      <settings>
            <label/>
      </settings>
      <!-- First Field Should be Primary key -->
      
        <field name="id" formElement="input">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="source" xsi:type="string">{Data_Source_Prefix}</item>
                </item>
            </argument>
            <settings>
                <dataType>text</dataType>
                <visible>false</visible>
                <dataScope>{Database_Table_Primary_key_Name}</dataScope>
            </settings>
        </field>  
        <field name="{Database_Table_FIELD_ONE}" formElement="input">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <!-- source is user defined -->
                    <item name="source" xsi:type="string">{Data_Source_Prefix}</item>
                </item>
            </argument>
            <settings>
                <validation>
                    <rule name="required-entry" xsi:type="boolean">true</rule>
                </validation>
                <dataType>text</dataType>
                <label translate="true">{Field Label1}</label>
                <dataScope>{Database_Table_FIELD_ONE}</dataScope>
            </settings>
        </field>
        <field name="{Database_Table_FIELD_TWO}" formElement="input">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <!-- source is user defined -->
                    <item name="source" xsi:type="string">{Data_Source_Prefix}</item>
                </item>
            </argument>
            <settings>
                <validation>
                    <rule name="required-entry" xsi:type="boolean">true</rule>
                </validation>
                <dataType>text</dataType>
                <label translate="true">{Field Label2}</label>
                <dataScope>{Database_Table_FIELD_TWO}</dataScope>
            </settings>
        </field> 
                    
    </fieldset>    
</form>

User Define

  • js_config provider name should be <item name="provider" xsi:type="string">{Ui_Component_EDIT_FORM_Name_PREFIX}_form.{Data_Source_Prefix}_data_source</item> . First part {Ui_Component_EDIT_FORM_Name_PREFIX}_form is Should be same UI Form File NAME.

  • js_config provider's second part Data Source name > Format is {Data_Source_Prefix}_data_source .

  • primaryFieldName>{Database_Table_Primary_key_Name}</primaryFieldName> {Database_Table_Primary_key_Name} This Primary key Field of that table which is defined at Resource Model Class https://github.com/devamitbera/magento2-module-stucture/blob/master/5.build-model.md#create-resource-model-class

  • <dataSource name=""> should be same js config second part Format: {Data_Source_Prefix}_data_source

  • submitUrl path="{Admin_Route_Id}/{ControllerName_LowerCase}/{Save_ActionFileName_In_LowerCase}" Save Ur route path.

Example Sample File location https://github.com/devamitbera/magento2-module-stucture/blob/master/module-row/app/code/StackExchange/Example/view/adminhtml/ui_component/example_ui_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">
            <!-- Data source provide Name with format 
             UIComponentFilename.UIComponentFilename_data_source
             -->            
                        
            <item name="provider" xsi:type="string">example_ui_form.example_ui_form_data_source</item>
        </item>
        <item name="label" xsi:type="string" translate="true">General Information</item>
        <item name="template" xsi:type="string">templates/form/collapsible</item>
    </argument>
    <!-- Mapping Data  with Ui component -->
    <settings>
        <!-- Adding Save and Delete and other button at here -->
        <buttons>
            <button name="save" class="StackExchange\Example\Block\Adminhtml\Edit\Form\SaveButton"/>
             <button name="delete" class="StackExchange\Example\Block\Adminhtml\Edit\Form\DeleteButton"/>
             <button name="back" class="StackExchange\Example\Block\Adminhtml\Edit\Form\BackButton"/>
             <button name="reset" class="StackExchange\Example\Block\Adminhtml\Edit\Form\ResetButton"/>
             <button name="new" class="StackExchange\Example\Block\Adminhtml\Edit\Form\NewButton"/>
        </buttons>
        <namespace>example_ui_form</namespace>
        <dataScope>data</dataScope>
        <deps>
            <dep>example_ui_form.example_ui_form_data_source</dep>
        </deps>
    </settings>
    <!-- define Data source Name-->
    <!-- source name formar == UIComponentFilename_data_source -->
    <dataSource name="example_ui_form_data_source">
        <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>
        <settings>
            <!--Save Url -->
            <submitUrl path="exampleadminid/example/save"/>
        </settings>
        <!-- Declare Data provide Php class and it user defined Class-->
        <dataProvider class="StackExchange\Example\Ui\Model\ExampleDataProvider" 
                      name="example_ui_form_data_source">
            <settings>
                <!-- Url parameter name for getting  which corresponding to Db 
                table primary
                -->
                <requestFieldName>example_id</requestFieldName>
                <primaryFieldName>id</primaryFieldName><!-- Db table primary key -->
            </settings>
        </dataProvider>
    </dataSource>
    <!-- Add Field to Edit Form -->
    <!-- FieldSet name is user Defined -->
    <fieldset name="general">
      <settings>
            <label/>
      </settings>
      <!-- First Field Should be Primary key -->
      
        <field name="{Database_Table_Primary_key_Name}" formElement="input">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="source" xsi:type="string">example_ui</item>
                </item>
            </argument>
            <settings>
                <dataType>text</dataType>
                <visible>false</visible>
                <dataScope>id</dataScope>
            </settings>
        </field>  
        <field name="name" formElement="input">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <!-- source is user defined -->
                    <item name="source" xsi:type="string">example_ui</item>
                </item>
            </argument>
            <settings>
                <validation>
                    <rule name="required-entry" xsi:type="boolean">true</rule>
                </validation>
                <dataType>text</dataType>
                <label translate="true">Student Name</label>
                <dataScope>name</dataScope>
            </settings>
        </field>
        <field name="age" formElement="input">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <!-- source is user defined -->
                    <item name="source" xsi:type="string">example_ui</item>
                </item>
            </argument>
            <settings>
                <validation>
                    <rule name="required-entry" xsi:type="boolean">true</rule>
                    <rule name="validate-zero-or-greater" xsi:type="boolean">true</rule>
                </validation>
                <dataType>text</dataType>
                <label translate="true">Student Age</label>
                <dataScope>age</dataScope>
            </settings>
        </field> 
        <!-- Add Drop Down field-->    
        <!-- define A Php Class which  provide list of Options and its label and value-->
        <field name="gender" formElement="select">
             <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="source" xsi:type="string">example_ui</item>
                </item>
            </argument>
            <settings>
                <validation>
                    <rule name="required-entry" xsi:type="boolean">true</rule>
                    <rule name="validate-select" xsi:type="boolean">true</rule>
                </validation>                
                <dataType>select</dataType>
                <label translate="true">Gender</label>
                <dataScope>gender</dataScope>
            </settings>
            <formElements>
                <select>
                    <settings>
                        <options class="StackExchange\Example\Ui\Component\Form\Field\Gender"/>
                        <caption translate="true">-- Please Select --</caption>
                    </settings>
                </select>
            </formElements>           
        </field> 
        <!-- Date field -->
        <field name="create_at" formElement="date">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="source" xsi:type="string">example_ui</item>
                </item>
            </argument>
            <settings>
                <validation>
                    <rule name="validate-date" xsi:type="boolean">true</rule>
                </validation>
                <dataType>text</dataType>
                <label translate="true">To</label>
                <dataScope>create_at</dataScope>
            </settings>
        </field>                         
    </fieldset>    
</form>

7. DataProviderClassName for provide data for Form.

Create a php data provider for provide data for edit form.

File Location and Name: app/code/{Vendor}/{ModuleName}/Ui/Model/{DataProviderClassName}.php

Format:

<?php

namespace {Vendor}\{ModuleName}\Ui\Model;

use Magento\Framework\App\Request\DataPersistorInterface;
use {Vendor}\{ModuleName}\Model\ResourceModel\{YourResourceModelName}\CollectionFactory;

class {DataProviderClassName} extends \Magento\Ui\DataProvider\ModifierPoolDataProvider
{
    protected $collection;
    /**
     * @var DataPersistorInterface
     */
    private $dataPersistor;

    /**
     * @var CollectionFactory
     */
    private $collectionFactory;

    protected $loadedData;

    public function __construct(
        $name,
        $primaryFieldName,
        $requestFieldName,
        DataPersistorInterface $dataPersistor,
        CollectionFactory $collectionFactory,
        array $meta = [],
        array $data = [],
        \Magento\Ui\DataProvider\Modifier\PoolInterface $pool = null
    ) {
        $this->collectionFactory = $collectionFactory;
        /**
         * It most important assign ColectionFactoty to collection
         */
        $this->collection  = $collectionFactory->create();
        $this->dataPersistor = $dataPersistor;
        parent::__construct(
            $name,
            $primaryFieldName,
            $requestFieldName,
            $meta,
            $data,
            $pool
        );
    }
    public function getData()
    {
        if (isset($this->loadedData)) {
            return $this->loadedData;
        }

        $items = $this->collection->getItems();
        /**
         * @var \{Vendor}\{ModuleName}\Model\{YourModel} $item
         */
        foreach ($items as $item) {
            $this->loadedData[$item->getId()] = $item->getData();
        }
        /**
         *  a variable to use future use for persist data from save Url
         */
        $data= $this->dataPersistor->get('{data_persistor_Name}');
        /**
         * it use during new item create from New form
         */
        if (!empty($data)) {
            $item = $this->collection->getNewEmptyItem();
            $item->setData($data);
            $this->loadedData[$item->getId()] = $item->getData();

            /**
             * Clear Previous One
             */
            $this->dataPersistor->clear('{data_persistor_Name}');
        }
        return $this->loadedData;
    }
}

User Define

  • {data_persistor_Name} is An user defined variable which used share data between save Action & news Record create

Here , you need to inject Collection Class which is defined at https://github.com/devamitbera/magento2-module-stucture/blob/master/5.build-model.md#create-collection-class

Example

<?php

namespace StackExchange\Example\Ui\Model;

use Magento\Framework\App\Request\DataPersistorInterface;
use StackExchange\Example\Model\ResourceModel\Student\CollectionFactory;

class ExampleDataProvider extends \Magento\Ui\DataProvider\ModifierPoolDataProvider
{
    protected $collection;
    /**
     * @var DataPersistorInterface
     */
    private $dataPersistor;

    /**
     * @var CollectionFactory
     */
    private $studentCollectionFactory;

    protected $loadedData;

    public function __construct(
        $name,
        $primaryFieldName,
        $requestFieldName,
        DataPersistorInterface $dataPersistor,
        CollectionFactory $studentCollectionFactory,
        array $meta = [],
        array $data = [],
        \Magento\Ui\DataProvider\Modifier\PoolInterface $pool = null
    ) {
        $this->studentCollectionFactory = $studentCollectionFactory;
        /**
         * It most important assign ColectionFactoty to collection
         */
        $this->collection  = $studentCollectionFactory->create();
        $this->dataPersistor = $dataPersistor;
        parent::__construct(
            $name,
            $primaryFieldName,
            $requestFieldName,
            $meta,
            $data,
            $pool
        );
    }
    public function getData()
    {
        if (isset($this->loadedData)) {
            return $this->loadedData;
        }

        $items = $this->collection->getItems();
        /**
         * @var \StackExchange\Example\Model\Student $student
         */
        foreach ($items as $student) {
            $this->loadedData[$student->getId()] = $student->getData();
        }
        /**
         *  a variable to use future use for persist data from save Url
         */
        $data= $this->dataPersistor->get('example_data');
        /**
         * it use during new item create from New form
         */
        if (!empty($data)) {
            $student = $this->collection->getNewEmptyItem();
            $student->setData($data);
            $this->loadedData[$student->getId()] = $student->getData();

            /**
             * Clear Previous One
             */
            $this->dataPersistor->clear('example_data');
        }
        return $this->loadedData;
    }
}

Location for example file: https://github.com/devamitbera/magento2-module-stucture/blob/master/module-row/app/code/StackExchange/Example/Ui/Model/ExampleDataProvider.php