How to Add Dynamic Rows in System Configuration in Magento 2?

Dynamic rows are something that can be very helpful at the time of saving the dynamic collection of records. While developing an extension, we must offer configuration to set the value globally for the website and operate at many places in the extension. When it comes to Magento 2, it offers a huge variety of UI components form fields. Out of which, dynamic rows are very important for collecting the records. It also offers the functionality to add, delete, and edit rows.

In dynamic rows, you can set various UI components fields such as textbox, dropdown, multi-select, and many more. So, in order to add dynamic rows, Let me help you with a step by step guide to add dynamic rows in the system configuration.

Steps of Dynamic Rows in System Configuration in Magento 2:

1) We assume that you have created simple module. Add this below code in your system.xml file at app/code/MD/Helloworld/etc/adminhtml/ :

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Config:etc/system_file.xsd">
    <system>
        <tab id="mdmodule" translate="label" sortOrder="50">
            <label>MD</label>
        </tab>
        <section id="section_extension" showInDefault="1">
            <tab>mdmodule</tab>
            <label>Helloworld</label>
            <resource>MD_Helloworld::config_extension</resource>
            <group id="general" translate="label" type="text" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="1">
                <label>Configuration</label>
                <field id="dynamic_field" translate="label" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="1">
                    <label>Dynamic Field</label>
                    <backend_model>MD\Helloworld\Block\Adminhtml\Config\Backend\ArraySerialized</backend_model>
                    <frontend_model>MD\Helloworld\Block\Adminhtml\DynamicFieldData</frontend_model>
                </field>
            </group>
        </section>
    </system>
</config>

2) Thereafter, create ArraySerialized.php file to save value in the serialized format at app/code/MD/Helloworld/etc/adminhtml/Config/Backend/ and paste the below code :

<?php
namespace MD\Helloworld\Block\Adminhtml\Config\Backend;
use Magento\Framework\App\Cache\TypeListInterface;
use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Framework\App\Config\Value as ConfigValue;
use Magento\Framework\Data\Collection\AbstractDb;
use Magento\Framework\Model\Context;
use Magento\Framework\Model\ResourceModel\AbstractResource;
use Magento\Framework\Registry;
use Magento\Framework\Serialize\SerializerInterface;
class ArraySerialized extends ConfigValue
{
    protected $serializer;
    public function __construct(
        SerializerInterface $serializer,
        Context $context,
        Registry $registry,
        ScopeConfigInterface $config,
        TypeListInterface $cacheTypeList,
        AbstractResource $resource = null,
        AbstractDb $resourceCollection = null,
       array $data = []
    ) {
        $this->serializer = $serializer;
        parent::__construct($context, $registry, $config, $cacheTypeList, $resource, $resourceCollection, $data);
    }
    public function beforeSave()
    {
        $value = $this->getValue();
        unset($value['__empty']);
        $encodedValue = $this->serializer->serialize($value);
        $this->setValue($encodedValue);
    }
    protected function _afterLoad()
    {
        $value = $this->getValue();
        if ($value) {
            $decodedValue = $this->serializer->unserialize($value);
            $this->setValue($decodedValue);
        }
    }
}

3) After that, CreateDynamicFieldData.php file in order to display data in admin at app/code/MD/Helloworld/Block/Adminhtml/ and paste the below code :

<?php
namespace MD\Helloworld\Block\Adminhtml;
use Magento\Config\Block\System\Config\Form\Field\FieldArray\AbstractFieldArray;
use Magento\Framework\DataObject;
use MD\Helloworld\Block\Adminhtml\Form\Field\CustomColumn;
class DynamicFieldData extends AbstractFieldArray {
private $dropdownRenderer;
       protected function _prepareToRender() {
              $this->addColumn(
                     'attribute_name',
              [
                            'label' => __('Attribute Name'),
                            'class' => 'required-entry',
                     ]
              );
              $this->addColumn(
                     'dropdown_field',
                     [
                            'label' => __('Dropdown'),
                            'renderer' => $this->getDropdownRenderer(),
                     ]
              );
              $this->_addAfter = false;
              $this->_addButtonLabel = __('Add');
       }
       protected function _prepareArrayRow(DataObject $row) {
              $options = [];
              $dropdownField = $row->getDropdownField();
              if ($dropdownField !== null) {
                     $options['option_' . $this->getDropdownRenderer()->calcOptionHash($dropdownField)] = 'selected="selected"';
              }
              $row->setData('option_extra_attrs', $options);
       }
       private function getDropdownRenderer() {
              if (!$this->dropdownRenderer) {
                     $this->dropdownRenderer = $this->getLayout()->createBlock(
                            CustomColumn::class,
                            '',
                            ['data' => ['is_render_to_js_template' => true]]
                     );
              }
              return $this->dropdownRenderer;
       }
}

4) Lastly, Create CustomColumn.php file to list items of dropdown in admin atapp/code/MD/Helloworld/Block/Adminhtml/Form/Field/ and paste the below code.

<?php
namespace MD\Helloworld\Block\Adminhtml\Form\Field;
use Magento\Framework\View\Element\Html\Select;
class CustomColumn extends Select
{
    public function setInputName($value)
    {
        return $this->setName($value);
    }
    public function setInputId($value)
    {
        return $this->setId($value);
    }
    public function _toHtml()
    {
        if (!$this->getOptions()) {
            $this->setOptions($this->getSourceOptions());
        }
        return parent::_toHtml();
    }

    private function getSourceOptions()
    {
        return [
            ['label' => 'Yes', 'value' => '1'],
            ['label' => 'No', 'value' => '0'],
       ];
    }
}

Additionally, we also included a dropdown field in dynamic rows in system configuration. You will be able to save dropdown value using this example.

That’s it !!!

Now, All you need to do is clear the cache and check it in your admin panel.

Output :

Dynamic Field

 

Also read: How to Add Color Picker in Magento 2 System Configuration?

Concluding Note:

Here, we have come to an end of this tutorial. Hope this have been helpful to you in order to create dynamic row in the system configuration of your Magento store. Let us know if we missed out anything. If there is any query, feel free to contact us. Meanwhile, check out our newly launched Magento Agency.