Menu Close
    Convert your store into Magento 2 Multi Vendor Marketplace

    Magento 2 Development 19: Multi tab form

    Till now we have seen two ways to create form. There are multiple ways to create form and there are multiple types of form that can be created.

    In this blog we will see how to create multi tab form like you see in the customer edit section. You can create this form with ui component or the widget. Here I will create it with widget. But I will advise you to create the multi tab structure with ui component as an exercise.


    First of all we will edit the layout file view/adminhtml/layout/blogmanager_manage_edit.xml

    <?xml version="1.0"?>
    <page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="admin-2columns-left" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
        <body>
            <referenceContainer name="left">
                <block class="Webkul\BlogManager\Block\Adminhtml\Blog\Edit\Tabs" name="blog_edit_tabs"/>
            </referenceContainer>
            <referenceContainer name="content">
                <block class="Webkul\BlogManager\Block\Adminhtml\Blog\Edit" name="blog_edit"/>
            </referenceContainer>
        </body>
    </page>

    Since we will be using 2 columns layout, one for tab and the other for the form itself, we need to specify the layout type as admin-2columns-left. In the left column we have added the tabs block and in the right or the main column we have added the main form class which is same as before.


    We will keep the Block/Adminhtml/Blog/Edit.php class as same as before. But we have to edit the form class Block/Adminhtml/Blog/Edit/Form.php as shown below

    <?php
    namespace Webkul\BlogManager\Block\Adminhtml\Blog\Edit;
    
    class Form extends \Magento\Backend\Block\Widget\Form\Generic
    {
        protected function _prepareForm()
        {
            $form = $this->_formFactory->create(
                ['data' => [
                                'id' => 'edit_form',
                                'enctype' => 'multipart/form-data',
                                'action' => $this->getData('action'),
                                'method' => 'post'
                            ]
                ]
            );
            $form->setUseContainer(true);
            $this->setForm($form);
            return parent::_prepareForm();
        }
    }
    

    As you can see we have removed all the field from this class. And we have kept only the form attributes that is because this class will act as the main form. And in this main form we will attach the fields related to each tabs. Also note that the form id is edit_form.


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

    <?php
    namespace Webkul\BlogManager\Block\Adminhtml\Blog\Edit;
    
    class Tabs extends \Magento\Backend\Block\Widget\Tabs
    {
        public function __construct(
            \Magento\Backend\Block\Template\Context $context,
            \Magento\Framework\Json\EncoderInterface $jsonEncoder,
            \Magento\Backend\Model\Auth\Session $authSession,
            \Magento\Framework\Registry $coreRegistry,
            array $data = []
        ) {
            $this->_coreRegistry = $coreRegistry;
            parent::__construct($context, $jsonEncoder, $authSession, $data);
        }
    
        protected function _construct()
        {
            parent::_construct();
            $this->setId('blog_tabs');
            $this->setDestElementId('edit_form');
            $this->setTitle(__('Blog Data'));
        }
    
        protected function _prepareLayout()
        {
            $this->addTab(
                'main',
                [
                    'label' => __('Blog Data'),
                    'content' => $this->getLayout()->createBlock(
                        'Webkul\BlogManager\Block\Adminhtml\Blog\Edit\Tab\Main'
                    )->toHtml(),
                    'active' => true
                ]
            );
    
            $this->addTab(
                'status',
                [
                    'label' => __('Blog Status'),
                    'content' => $this->getLayout()->createBlock(
                        'Webkul\BlogManager\Block\Adminhtml\Blog\Edit\Tab\Status'
                    )->toHtml()
                ]
            );
    
            return parent::_prepareLayout();
        }
    }
    

    Now here you can see with setDestElementId method we have set the destination element for the tabs output as edit_form which is the id of the form that we created earlier.

    In the _prepareLayout function we can add the tabs. The code for adding the tab is very self explanatory. We have given an id to the tab and added label. We have also mentioned which tab should be active when we first load the page. In the content param we have mentioned the block class that will produce the html content for this tab.

    Important thing to mention here is that we can also load ajax content in the tab. And this is very common practice when we show data in grid form in a tab. The syntax for tab with ajax data is given below,

    $this->addTab(
        'tab_id',
        [
            'label' => __('Tab Label'),
            'url' => $this->getUrl('frontname/controller/action', ['param' => $value]),
            'class' => 'ajax'
        ]
    );
    

    Instead of content we are using url param and we pass the ajax url to load. We can also pass some param if we want to load the relevant data.
    One use case in our scenario can be if we show the comments of a blog in a grid. There we will pass the blog id in param and load the comments with ajax.


    Let’s see how we can create the two tab classes. First we will create the main tab as Block/Adminhtml/Blog/Edit/Tab/Main.php

    <?php
    namespace Webkul\BlogManager\Block\Adminhtml\Blog\Edit\Tab;
    
    class Main extends \Magento\Backend\Block\Widget\Form\Generic
    {
        public function __construct(
            \Magento\Backend\Block\Template\Context $context,
            \Magento\Framework\Registry $registry,
            \Magento\Framework\Data\FormFactory $formFactory,
            \Webkul\BlogManager\Model\Blog\Status $blogStatus,
            array $data = []
        ) {
            $this->blogStatus = $blogStatus;
            parent::__construct($context, $registry, $formFactory, $data);
        }
    
        protected function _prepareForm()
        {
           
            $model = $this->_coreRegistry->registry('blog_data');
    
            $form = $this->_formFactory->create();
    
            $form->setHtmlIdPrefix('blogmanager_');
    
            $fieldset = $form->addFieldset(
                'base_fieldset',
                ['legend' => __('Edit Blog'), '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,
                ]
            );
            
            $form->setValues($model->getData());
            $this->setForm($form);
    
            return parent::_prepareForm();
        }
    }
    

    It is very similar to what we saw in previous blog. There are only two differences. We have removed the $form->setUseContainer(true); line from the code because it will create nested form. Also you can see while creating the form we have not passed the data param as we did earlier. That is because we are using the main form itself.

    Now let’s create the other tab, Block/Adminhtml/Blog/Edit/Tab/Status.php

    <?php
    namespace Webkul\BlogManager\Block\Adminhtml\Blog\Edit\Tab;
    
    class Status extends \Magento\Backend\Block\Widget\Form\Generic
    {
        public function __construct(
            \Magento\Backend\Block\Template\Context $context,
            \Magento\Framework\Registry $registry,
            \Magento\Framework\Data\FormFactory $formFactory,
            \Webkul\BlogManager\Model\Blog\Status $blogStatus,
            array $data = []
        ) {
            $this->blogStatus = $blogStatus;
            parent::__construct($context, $registry, $formFactory, $data);
        }
    
        protected function _prepareForm()
        {
           
            $model = $this->_coreRegistry->registry('blog_data');
    
            $form = $this->_formFactory->create();
    
            $form->setHtmlIdPrefix('blogmanager_');
    
            $fieldset = $form->addFieldset(
                'base_fieldset',
                ['legend' => __('Edit Blog'), 'class' => 'fieldset-wide']
            );
    
            $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());
            $this->setForm($form);
    
            return parent::_prepareForm();
        }
    }
    

    It is essentially same as the main class. So no explanation is needed here.

    Now when you click on edit, you should see something like,

    ezgif.com-gif-maker-5


    Note that sometimes you may want to create a custom form with custom design. You can do that too in magento by creating own form with phtml file. I will not cover it but you can easily find it in many blogs and follow along.


    Next Blog -> Magento 2 Development 20: Add Button

    Previous Blog -> Magento 2 Development 18: Form Widget

    . . .
    Discuss on Helpdesk

    Leave a Comment

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


    Be the first to comment.

    Back to Top