Menu Close
    Convert your store into Magento 2 Multi Vendor Marketplace

    Magento 2 Development 18: Form Widget

    As promised in the last blog, here we will learn about how to add form in admin side with form widget, which we will manage with Block class. This is very popular technique and most of the time you will find forms are created with this technique. We can also use .phtml to create form by slight modification in this technique.

    First of we will have to replace the ui component with block. So let’s edit the layout file for that view/adminhtml/layout/blogmanager_manage_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">
        <body>
            <referenceContainer name="content">
                <block class="Webkul\BlogManager\Block\Adminhtml\Blog\Edit" name="blog_edit"/>
            </referenceContainer>
        </body>
    </page>

    Here as you can see we have removed the uicomponent tag and added block tag. So no code related to the ui component form will be executed now.


    Before creating the block class let’s modify the edit controller as well, Controller/Adminhtml/Manage/Edit.php

    <?php
    namespace Webkul\BlogManager\Controller\Adminhtml\Manage;
    
    use Magento\Backend\App\Action;
    use Magento\Framework\Controller\ResultFactory;
    
    class Edit extends Action
    {
        public function __construct(
            \Magento\Backend\App\Action\Context $context,
            \Magento\Framework\Registry $coreRegistry,
            \Webkul\BlogManager\Model\BlogFactory $blogFactory
        ) {
            parent::__construct($context);
            $this->coreRegistry = $coreRegistry;
            $this->blogFactory = $blogFactory;
        }
    
        public function execute()
        {
            $blogId = $this->getRequest()->getParam('id');
            $blogModel = $this->blogFactory->create()->load($blogId);
            $this->coreRegistry->register('blog_data', $blogModel);
            $resultPage = $this->resultFactory->create(ResultFactory::TYPE_PAGE);
            $resultPage->getConfig()->getTitle()->prepend(__("Edit Blog"));       
            return $resultPage;
        }
    
        public function _isAllowed()
        {
            return $this->_authorization->isAllowed('Webkul_BlogManager::edit');
        }
    }
    

    The main changes we did here is that we loaded the blog model based on the id that we get from the url param. And we are storing the model with help of core registry. We will later retrieve the model when we need to fill the form data.

    What is core registry?
    Core registry is used to store global variable. You can store global variables via register() method and fetch value of variables via registry() method. Magento registry stores data to memory which is specific to a particular request and for a duration of that request only. 


    Now let’s create the block class, Block/Adminhtml/Blog/Edit.php

    <?php
    namespace Webkul\BlogManager\Block\Adminhtml\Blog;
    
    class Edit extends \Magento\Backend\Block\Widget\Form\Container
    {
        protected function _construct()
        {
            $this->_objectId = 'id';
            $this->_blockGroup = 'Webkul_BlogManager';
            $this->_controller = 'adminhtml_blog';
            parent::_construct();
            $this->buttonList->remove('delete');
        }
    }

    There are few things to note in this code. First of all we are using _construct() instead of __construct() , did you notice the difference? There is a underscore ( _ ) missing from the first one. You can think of _construct() as Magento’s constructor, which gets called inside the __construct(), which is php’s constructor or the actual constructor.

    We can not assign any string to $this->_blockGroup it must be the module name. And similarly for $this->_controller we need to assign current folder path relative to the Block folder, which is Adminhtml/Blog , which get converted to adminhtml_blog. If we do not follow these patterns then we will get exceptions.

    From this “constructor” we can manage the buttons. That means we can add new buttons and update or delete default buttons which are save, delete, reset and back.


    Now we need to create a folder parallel to this class with the same name as the class name i.e. Edit. And inside that we need to create a class named Form. So the file will be like Block/Adminhtml/Blog/Edit/Form.php

    <?php
    namespace Webkul\BlogManager\Block\Adminhtml\Blog\Edit;
    
    class Form extends \Magento\Backend\Block\Widget\Form\Generic
    {
        protected function _prepareForm()
        {
            $model = $this->_coreRegistry->registry('blog_data');
    
            $form = $this->_formFactory->create(
                ['data' => [
                                'id' => 'edit_form',
                                'enctype' => 'multipart/form-data',
                                'action' => $this->getData('action'),
                                'method' => 'post'
                            ]
                ]
            );
    
            $form->setHtmlIdPrefix('blogmanager_');
    
            $fieldset = $form->addFieldset(
                'base_fieldset',
                ['legend' => __('Blog Data'), 'class' => 'fieldset-wide']
            );
    
            $fieldset->addField('entity_id', 'hidden', ['name' => 'entity_id']);
    
            $fieldset->addField(
                'title',
                'text',
                [
                    'name' => 'title',
                    'label' => __('Title'),
                    'id' => 'title',
                    'title' => __('Title'),
                    'class' => 'required-entry',
                    'required' => true,
                ]
            );
    
            $fieldset->addField(
                'content',
                'textarea',
                [
                    'name' => 'content',
                    'label' => __('Content'),
                    'id' => 'content',
                    'title' => __('Content'),
                    'class' => 'required-entry',
                    'required' => true,
                ]
            );
    
            $fieldset->addField(
                'status',
                'select',
                [
                    'name' => 'status',
                    'label' => __('Status'),
                    'options' => [0=>__('Disabled'), 1=>__('Enabled')],
                    'id' => 'status',
                    'title' => __('Status'),
                    'class' => 'required-entry',
                    'required' => true,
                ]
            );
            
            $form->setValues($model->getData());
            $form->setUseContainer(true);
            $this->setForm($form);
    
            return parent::_prepareForm();
        }
    }
    

    Here if you have any other class dependency then you can create the constructor based on the parent class’s constructor.

    We will create and prepare the form with the help of _prepareForm method.

    Notice here we have used core registry to retrieve the loaded model. We can also load the blog model with factory class again but magento generally usage this approach.

    We have created the actual form itself with various form attributes with the help of $this->_formFactory->create().

    We can add multiple fieldsets with $form->addFieldset(). And now in the fieldset we can add different fields with $fieldset->addField() method.

    In addField we have passed three arguments. First argument will be used for setting the field data, second argument is to specify the type of the field and the third argument is an array which is used to manage the field’s attributes such as name, class, etc.

    To set the values in the fields based on the data we get in the model. We have written $form->setValues($model->getData());. After that we need to set the form as $this->setForm($form); so that it shows up.


    Now if we click on the edit button we will see the form as shown below,

    edit form


    Now that we have created the form. Let’s create the save controller as Controller/Adminhtml/Manage/Save.php

    <?php
    namespace Webkul\BlogManager\Controller\Adminhtml\Manage;
    
    use Magento\Backend\App\Action;
    use Magento\Backend\App\Action\Context;
    
    class Save extends Action
    {
        public $blogFactory;
    
        public function __construct(
            Context $context,
            \Webkul\BlogManager\Model\BlogFactory $blogFactory
        ) {
            $this->blogFactory = $blogFactory;
            parent::__construct($context);
        }
    
        public function execute()
        {
            $resultRedirect = $this->resultRedirectFactory->create();
            $data = $this->getRequest()->getParams();
            if (isset($data['entity_id']) && $data['entity_id']) {
                $model = $this->blogFactory->create()->load($data['entity_id']);
                $model->setTitle($data['title'])
                    ->setContent($data['content'])
                    ->setStatus($data['status'])
                    ->save();
                $this->messageManager->addSuccess(__('You have updated the blog successfully.'));
            }    
            return $resultRedirect->setPath('*/*/');
        }
    
        public function _isAllowed()
        {
            return $this->_authorization->isAllowed('Webkul_BlogManager::save');
        }
    }

    We have seen all of these codes in one place or another. So you should be familiar with them by now. If not then please revisit few blogs.


    Now when you edit and save the blog. You should see something like below,

    edit form


    Next Blog -> Magento 2 Development 19: Multi tab form

    Previous Blog -> Magento 2 Development 17: uiComponent form

    . . .
    Discuss on Helpdesk

    Leave a Comment

    Your email address will not be published. Required fields are marked*


    2 comments

  • jordan
    a very helpful article, hope you will publish the next one soon.
    • Sanjay Chouhan (Moderator)
      Thanks, we will be publishing a lot more in coming days.
  • Back to Top