Reading list Switch to dark mode

    Magento 2 Development 21: Form Widget

    Updated 12 March 2024

    As promised in the last blog, here we will learn about how to add forms on the admin side with the form widget, which we will manage with Block class. This is a 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.

    Create the layout file

    First of we will have to replace the ui component with a block. So let’s edit the layout file for that view/adminhtml/layout/blogmanager_manage_edit.xml 

    Updated code for view/adminhtml/layout/blogmanager_manage_edit.xml  file

    <?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 a block tag. So no code related to the ui component form will be executed now.

    Edit Controller file to Edit the blog

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

    Searching for an experienced
    Magento 2 Company ?
    Find out More

    Updated code for Controller/Adminhtml/Manage/Edit.php file

    <?php
    namespace Webkul\BlogManager\Controller\Adminhtml\Manage;
    
    use Magento\Backend\App\Action;
    use Magento\Framework\Controller\ResultFactory;
    
    class Edit extends Action
    {
        /**
         * @var \Magento\Framework\Registry
         */
        protected $coreRegistry;
    
        /**
         * @var \Webkul\BlogManager\Model\BlogFactory
         */
        protected $blogFactory;
    
        /**
         * Dependency Initilization
         *
         * @param \Magento\Backend\App\Action\Context $context
         * @param \Magento\Framework\Registry $coreRegistry
         * @param \Webkul\BlogManager\Model\BlogFactory $blogFactory
         */
        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;
        }
    
        /**
         * Provides content
         *
         * @return \Magento\Framework\View\Result\Page
         */
        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;
        }
    
        /**
         * Check Autherization
         *
         * @return boolean
         */
        public function _isAllowed()
        {
            return $this->_authorization->isAllowed('Webkul_BlogManager::edit');
        }
    }

    The main change 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 the help of the core registry. We will later retrieve the model when we need to fill in the form data.

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

    Create a Block file to Edit the blog

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

    Code for Block/Adminhtml/Blog/Edit.php file

    <?php
    namespace Webkul\BlogManager\Block\Adminhtml\Blog;
    
    class Edit extends \Magento\Backend\Block\Widget\Form\Container
    {
        /**
         * @var string
         */
        protected $_objectId;
    
        /**
         * @var string
         */
        protected $_blockGroup;
    
        /**
         * @var string
         */
        protected $_controller;
    
        /**
         * @var Magento\Backend\Block\Widget\Button\ButtonList
         */
        protected $buttonList;
    
        /**
         * Dependency Initilization
         *
         * @return void
         */
        protected function _construct()
        {
            $this->_objectId = 'id';
            $this->_blockGroup = 'Webkul_BlogManager';
            $this->_controller = 'adminhtml_blog';
            $this->buttonList->remove('delete');
            parent::_construct();
        }
    }

    There are a few things to note in this code. First of all, we are using _construct() instead of __construct(), did you notice the difference? There is an underscore ( _ ) missing from the first one. We 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 the current folder path relative to the Block folder, which is Adminhtml/Blog , which gets 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.

    Create a Block file to create a Form

    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

    Code for Block/Adminhtml/Blog/Edit/Form.php file

    <?php
    namespace Webkul\BlogManager\Block\Adminhtml\Blog\Edit;
    
    class Form extends \Magento\Backend\Block\Widget\Form\Generic
    {
        /**
         * Prepare form data
         *
         * @return \Magento\Backend\Block\Widget\Form
         */
        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 the _prepareForm method.

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

    Now, 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 the $fieldset->addField() method.

    In addField, we have passed three arguments. The first argument will be used for setting the field data, the 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

    Create a Controller to Save the form

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

    Code for Controller/Adminhtml/Manage/Save.php file

    <?php
    namespace Webkul\BlogManager\Controller\Adminhtml\Manage;
    
    use Magento\Backend\App\Action;
    use Magento\Backend\App\Action\Context;
    
    class Save extends Action
    {
        /**
         * @var \Webkul\BlogManager\Model\BlogFactory
         */
        protected $blogFactory;
    
        /**
         * Dependency Initilization
         *
         * @param Context $context
         * @param \Webkul\BlogManager\Model\BlogFactory $blogFactory
         */
        public function __construct(
            Context $context,
            \Webkul\BlogManager\Model\BlogFactory $blogFactory
        ) {
            $this->blogFactory = $blogFactory;
            parent::__construct($context);
        }
    
        /**
         * Provides content
         *
         * @return Magento\Framework\Controller\Result\Redirect
         */
        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('*/*/');
        }
    
        /**
         * Check Autherization
         *
         * @return boolean
         */
        public function _isAllowed()
        {
            return $this->_authorization->isAllowed('Webkul_BlogManager::save');
        }
    }

    We have seen all of these codes already. So you should be familiar with them by now. If not then please revisit those blogs.

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

    edit form


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

    Previous Blog -> Magento 2 Development 20: uiComponent form

    . . .

    Leave a Comment

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


    2 comments

  • jordan
    • Sanjay Chouhan (Moderator)
  • Back to Top

    Message Sent!

    If you have more details or questions, you can reply to the received confirmation email.

    Back to Home