
Many times in Module development there is some case we need to get dynamic data into system configuration. Magento 2 provides Dynamic Row UI-Component. Dynamic rows UI components provide the functionality to store the data as a collection of records. It provides functionality to add, edit and delete rows as many as needed. it offers a huge variety of UI components from fields. we can set many UI component fields in dynamic rows like textbox, dropdown, multiselect, etc.
Now we create a dynamic row with text, select and date field into system 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="test" translate="label" sortOrder="201">
<label>Test Date</label>
</tab>
<section id="test" translate="label" sortOrder="130" showInDefault="1" showInWebsite="1" showInStore="1">
<class>separator-top</class>
<label>Test Dynamic Row Demo</label>
<tab>test</tab>
<resource>Dolphin_DynamicRowDemo::test</resource>
<group id="general_setting"
translate="label"
type="text"
sortOrder="10"
showInDefault="1"
showInWebsite="1"
showInStore="1">
<label>General</label>
<field id="fieldname"
translate="label"
sortOrder="20"
showInDefault="1"
showInWebsite="1"
showInStore="1">
<label>Dynamic Row</label>
<backend_model>Dolphin\DynamicRowDemo\Block\Adminhtml\System\Config\ArraySerialized</backend_model>
<frontend_model>Dolphin\DynamicRowDemo\Block\Adminhtml\System\Config\DynamicFieldData</frontend_model>
</field>
</group>
</section>
</system>
</config>
<?php
namespace Dolphin\DynamicRowDemo\Block\Adminhtml\System\Config;
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();
if (isset($value['__empty'])) {
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);
}
}
}<?php
namespace Dolphin\DynamicRowDemo\Block\Adminhtml\System\Config;
use Dolphin\DynamicRowDemo\Block\Adminhtml\System\Config\Field\CustomColumn;
use Magento\Backend\Block\Template\Context;
use Magento\Config\Block\System\Config\Form\Field\FieldArray\AbstractFieldArray;
use Magento\Framework\DataObject;
use Magento\Framework\Registry;
class DynamicFieldData extends AbstractFieldArray
{
private $holidaysRenderer;
private $dateRenderer;
private $selectOptions;
public function __construct(
Context $context,
Registry $coreRegistry,
array $data = []
) {
$this->_coreRegistry = $coreRegistry;
parent::__construct($context, $data);
}
protected function _prepareToRender()
{
$this->addColumn(
'select_date',
[
'label' => __('Date'),
'id' => 'select_date',
'class' => 'daterecuring',
'style' => 'width:300px',
]
);
$this->addColumn(
'date_title',
[
'label' => __('Content'),
'class' => 'required-entry',
'style' => 'width:300px',
]
);
$this->addColumn(
'select_field',
[
'label' => __('Option'),
'renderer' => $this->getSelectFieldOptions(),
]
);
$this->_addAfter = false;
$this->_addButtonLabel = __('Add More');
}
protected function _prepareArrayRow(DataObject $row): void
{
$options = [];
$selectFieldData = $row->getSelectField();
if ($selectFieldData !== null) {
$options['option_' . $this->getSelectFieldOptions()->calcOptionHash($selectFieldData)] = 'selected="selected"';
}
$row->setData('option_extra_attrs', $options);
}
private function getSelectFieldOptions()
{
if (!$this->selectOptions) {
$this->selectOptions = $this->getLayout()->createBlock(
CustomColumn::class,
'',
['data' => ['is_render_to_js_template' => true]]
);
}
return $this->selectOptions;
}
protected function _getElementHtml(\Magento\Framework\Data\Form\Element\AbstractElement $element)
{
$html = parent::_getElementHtml($element);
$script = '<script type="text/javascript">
require(["jquery", "jquery/ui", "mage/calendar"], function (jq) {
jq(function(){
function bindDatePicker() {
setTimeout(function() {
jq(".daterecuring").datepicker( { dateFormat: "mm/dd/yy" } );
}, 50);
}
bindDatePicker();
jq("button.action-add").on("click", function(e) {
bindDatePicker();
});
});
});
</script>';
$html .= $script;
return $html;
}
}<?php
namespace Dolphin\DynamicRowDemo\Block\Adminhtml\System\Config\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'],
];
}
}
I hope this helps you. For any doubts regarding this topic, please write your doubts in the comments section.
Click one of our contacts below to chat on WhatsApp