Hello Magento Lovers,

We all need several configuration fields during the development of the Magento 2 Module. I would love to explain how to add dynamic fields in admin configuration using system.xml. These fields store data in table `core_config_data` in a serialized form which will reduce the complexity and resource of the database.

I am adding dynamic saler's information block to admin configuration

    <?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="magentofever" translate="label" sortOrder="10">
			<label>MageFever</label>
		</tab>
		<section id="magentofever_main" translate="label" sortOrder="130" showInDefault="1" showInWebsite="1" showInStore="1">
			<class>separator-top</class>
			<label>Add dynamic field to admin configurtion</label>
			<tab>MagentoFever</tab>
			<resource>Magefever::example_config</resource>
			<group id="general" translate="label" type="text" sortOrder="10" showInDefault="1" showInWebsite="0" showInStore="0"> 
               <label>General Configuration</label>
				<field id="saler_info" type="text" translate="label" sortOrder="30" showInDefault="1" showInWebsite="1" showInStore="1">
					<label>Saler's Info</label>
					<validate>required-entry</validate>
					<frontend_model>
						Magefever\Example\Block\Adminhtml\Form\Field\Salers
					</frontend_model>
					<backend_model>
						Magefever\Example\Model\Config\Backend\Holidays
					</backend_model>
				</field>
			</group>
		</section>
	</system>
</config>

	

Magefever\Example\Block\Adminhtml\Form\Field\Salers.php (BLOCK)

    <?php

namespace Magefever\Example\Block\Adminhtml\Form\Field;
class Salers extends \Magento\Config\Block\System\Config\Form\Field\FieldArray\AbstractFieldArray
{
    /**
     * {@inheritdoc}
     */ 
    public $_dateRenderer;
    public function __construct(
        \Magento\Backend\Block\Template\Context $context,
        array $data = []
    ) {
        parent::__construct( $context, $data );
    }
    public function _getDateColumnRenderer() {
        if( !$this->_dateRenderer ) {
            $this->_dateRenderer = $this->getLayout()->createBlock(
                '\Magefever\Example\Block\Adminhtml\Form\Field\Dob',
                '',
                [
                    'data' => [
                        'is_render_to_js_template' => true,
                        'date_format'              => 'dd/mm/Y'
                    ]
                ]
                );
        }
        return $this->_dateRenderer;
    }
    public function _prepareToRender() {
        $this->addColumn('firstname', ['label' => __('First Name'), 'class' => 'required-entry']);
        $this->addColumn('lastname', ['label' => __('Last Name')]);
        $this->addColumn('email',['label' => __('Email'), 'size' => '50px', 'class' => 'required-entry validate-email']);
        $this->addColumn( 'Date', [ 'label' => __( 'Birth Date' ),'renderer' => $this->_getDateColumnRenderer()]);
        $this->_addAfter       = false;
        $this->_addButtonLabel = __( 'Add' );
    }
}
?>
	

Magefever\Example\Block\Adminhtml\Form\Field\Dob.php (Block)

    <?php
namespace Magefeverver\Example\Block\Adminhtml\Form\Field;
class Dob extends \Magento\Framework\View\Element\Html\Date
{
    protected function _toHtml() {
        $html = '<input type="text" name="' . $this->getInputName() . '" id="' . $this->getInputId() . '" ';
        $html .= 'value="<%- ' . $this->getColumnName() .' %>" ';
        $html .= 'class="' . $this->getClass() . '" ' . $this->getExtraParams() . '/> ';
        $calendarYearsRange = $this->getYearsRange();
        $changeMonth        = $this->getChangeMonth();
        $changeYear         = $this->getChangeYear();
        $maxDate            = $this->getMaxDate();
        $showOn             = $this->getShowOn();
        $html .= '<script type="text/javascript">require(["jquery", "mage/calendar"], function($){ $("#' .
                 $this->getInputId() .
                 '").calendar({showsTime: ' .
                 ( $this->getTimeFormat() ? 'true' : 'false' ) .
                 ',' .
                 ( $this->getTimeFormat() ? 'timeFormat: "' .
                                            $this->getTimeFormat() .
                                            '",' : '' ) .
                 'dateFormat: "' .
                 $this->getDateFormat() .
                 '",buttonImage: "' .
                 $this->getImage() .
                 '",' .
                 ( $calendarYearsRange ? 'yearRange: "' .
                                         $calendarYearsRange .
                                         '",' : '' ) .
                 'buttonText: "' .
                 (string) new \Magento\Framework\Phrase(
                     'Select Date'
                 ) .
                 '"' . ( $maxDate ? ', maxDate: "' . $maxDate . '"' : '' ) .
                 ( $changeMonth === null ? '' : ', changeMonth: ' . $changeMonth ) .
                 ( $changeYear === null ? '' : ', changeYear: ' . $changeYear ) .
                 ( $showOn ? ', showOn: "' . $showOn . '"' : '' ) .
                 '})});<\'+\'/script>';
        return $html;
    }
}

	

Magefever\Example\Model\Config\Backend\Salers.php

    <?php
namespace Magefever\Example\Model\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 Salers extends ConfigValue
{
    protected $serializer;
    public function __construct(
        SerializerInterface $serializer = null,
        Context $context,
        Registry $registry,
        ScopeConfigInterface $config,
        TypeListInterface $cacheTypeList,
        AbstractResource $resource = null,
        AbstractDb $resourceCollection = null,
        array $data = []
    ) {
        $this->serializer = $serializer ?: \Magento\Framework\App\ObjectManager::getInstance()
            ->get(\Magento\Framework\Serialize\Serializer\Json::class);
        parent::__construct($context, $registry, $config, $cacheTypeList, $resource, $resourceCollection, $data);
    }
    protected function _afterLoad(){
        if($this->getValue()){
            $value = $this->getValue();
            $decodedValue = $this->serializer->unserialize($value);
            $this->setValue($decodedValue);
        }
    }

    public function beforeSave()
    {
        $value = $this->getValue();
        unset($value['__empty']);
        $encodedValue = $this->serializer->serialize($value);
        $this->setValue($encodedValue);
    }
}