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.