1

Is there any way to add & save dynamic rows in magento 2 system config?

I want to add the below fields :

Name

Link

Upload image

Any help would be appreciated.

11
  • any thoughts on this ?
    – user104369
    Apr 15, 2022 at 6:31
  • Are you need to create new grid with these fields or need to add in Store -> Configuration ?
    – Prits
    Apr 15, 2022 at 8:42
  • Hello @Prits, I am trying to create it in Store -> Configuration.
    – user104369
    Apr 15, 2022 at 8:47
  • Here is what I have tried - magento.stackexchange.com/questions/354870/….
    – user104369
    Apr 15, 2022 at 8:47
  • any thoughts on this ?
    – user104369
    Apr 15, 2022 at 10:15

1 Answer 1

1

Note: don't create object manager always inject as it is not recommended

XML file which is create back-end Field

File Path : app/code/Tnbl/Nodelivery/etc/adminhtml/system.xml

<?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="Tnbl" translate="label comment" sortOrder="100">
        <label>Data</label>
    </tab>
    <section id="order_section" translate="label comment" sortOrder="100" showInDefault="1" showInStore="1" showInWebsite="1">
        <label>Shipping Block Dates</label>
        <tab>Tnbl</tab>
        <resource>Tnbl_Nodelivery::tnbl_config</resource>
        <group id="order_settings" translate="label comment" sortOrder="10" showInDefault="1" showInStore="1" showInWebsite="1">
             <field id="excludedates" translate="label" sortOrder="100" showInDefault="1" showInWebsite="1" showInStore="1">
                <label>Data Calculation</label>
                <comment>data calculation</comment>
                <backend_model>Tnbl\Nodelivery\Model\Config\Backend\DatePickerList</backend_model>
                <frontend_model>Tnbl\Nodelivery\Block\Adminhtml\Form\Field\DatePickerList</frontend_model>
            </field>
        </group>
    </section>
</system>

Frontend File : /app/code/Tnbl/Nodelivery/Block/Adminhtml/Form/Field/DatePickerList.php

<?php

namespace Tnbl\Nodelivery\Block\Adminhtml\Form\Field;

class DatePickerList extends \Magento\Config\Block\System\Config\Form\Field\FieldArray\AbstractFieldArray
{
/**
 * Initialise form fields
 *
 * @return void
 */
protected $_imageRenderer;
protected function _prepareToRender()
{
    $this->addColumn('date', ['label' => __('Date'), 'class' => 'js-date-excluded-datepicker']);
    $this->addColumn('content', ['label' => __('Content')]);
    $this->addColumn(
        'image_thumb', [
            'label' => __('Thumbnail'),
            'renderer'  => $this->getImageColumnRenderer()
        ]
    );
    $this->_addAfter = false;
    $this->_addButtonLabel = __('Add Date');
    parent::_prepareToRender();
}

protected function getImageColumnRenderer() {
    if (!$this->_imageRenderer) {
        $this->_imageRenderer = $this->getLayout()->createBlock(
                \Tnbl\Nodelivery\Block\Adminhtml\Form\Field\Thumbnail::class, '', ['data' => ['is_render_to_js_template' => true]]
        );
    }
    return $this->_imageRenderer;
}

/**
 * Prepare existing row data object
 * Convert backend date format "2018-01-12" to front format "12/01/2018"
 *
 * @param \Magento\Framework\DataObject $row
 * @return void
 * @SuppressWarnings(PHPMD.UnusedFormalParameter)
 */
protected function _prepareArrayRow(\Magento\Framework\DataObject $row)
{
    $imagekey = 'image_val';
    $key = 'date';
    if (!isset($row[$key])) return;
    $rowId = $row['_id'];
    try {
        $sourceDate = \DateTime::createFromFormat('Y-m-d', $row[$key]);
        $renderedDate = $sourceDate->format('d/m/Y');
        $row[$key] = $renderedDate;
        $columnValues = $row['column_values'];
        $columnValues[$this->_getCellInputElementId($rowId, $key)] = $renderedDate;
        $row['column_values'] = $columnValues;
    } catch (\Exception $e) {
        // Just skipping error values
    }
}

/**
 * Get the grid and scripts contents
 *
 * @param \Magento\Framework\Data\Form\Element\AbstractElement $element
 * @return string
 */
protected function _getElementHtml(\Magento\Framework\Data\Form\Element\AbstractElement $element)
{
    $html = parent::_getElementHtml($element);

    $script = <<<JS
        <script type="text/javascript">
            // Bind click to "Add" buttons and bind datepicker to added date fields
            require(["jquery", "jquery/ui"], function (jq) {
                jq(function(){
                    function bindDatePicker() {
                        setTimeout(function() {
                            jq(".js-date-excluded-datepicker").datepicker( { dateFormat: "dd/mm/yy" } );
                        }, 50);
                    }
                    bindDatePicker();
                    jq("button.action-add").on("click", function(e) {
                        bindDatePicker();
                    });
                });
            });
        </script>
JS;
    $html .= $script;
    return $html;
}

}

File : app/code/Tnbl/Nodelivery/Model/Config/Backend/DatePickerList.php

<?php
    /**
     * Date Picker List Model
     *
     * @category   Scommerce
     * @package    Scommerce_Custom
     * @author     Sagar Nayyar
     *
     */
    namespace Tnbl\Nodelivery\Model\Config\Backend;
     
    class DatePickerList extends \Magento\Config\Model\Config\Backend\Serialized\ArraySerialized
    {
        /**
         * On save convert front value format like "12/01/2018" to backend format "2018-01-12"
         *
         * @return $this
         */
        public function beforeSave()
        {
            $value = [];
            $values = $this->getValue();
            foreach ((array)$values as $key => $data) {
                if ($key == '__empty') continue;
                if (!isset($data['date'])) continue;
                try {
                    $objectManager = \Magento\Framework\App\ObjectManager::getInstance();
                    $fileSystem = $objectManager->create('\Magento\Framework\Filesystem');
                    $mediaPath = $fileSystem->getDirectoryRead(\Magento\Framework\App\Filesystem\DirectoryList::MEDIA)->getAbsolutePath();
                    $storeManager = $objectManager->get('\Magento\Store\Model\StoreManagerInterface');
                    $mediaUrl =$storeManager->getStore()->getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_MEDIA);
                    $target_file = basename($data["image_thumb"]["name"]);
                    $image_temp = $data["image_thumb"]["tmp_name"];
                    move_uploaded_file($image_temp,$mediaPath.$target_file);
                    $date = \DateTime::createFromFormat('d/m/Y', $data['date']);
                    if($target_file){
                        $value[$key] = [
                            'date' => $date->format('Y-m-d'),
                            'content' => $data['content'],
                            'image_val' => $mediaUrl.$target_file,
                        ];
                    }else{
                        $value[$key] = [
                            'date' => $date->format('Y-m-d'),
                            'content' => $data['content'],
                        ];
                    }
                } catch (\Exception $e) {
                    // Just skipping error values
                }
            }
            $this->setValue($value);
            return parent::beforeSave();
        }
    }

Just Image preview is remaining rest all things is done.

If it helps you then upvote the answer.

13
  • Thank you very much @Prits. Can you please share an image? I just want to see how it looks like after the implementation.
    – user104369
    Apr 18, 2022 at 7:53
  • Hello @Prits, where do I need to put the beforeSave() method in which file? Can you please send module if possible ?
    – user104369
    Apr 18, 2022 at 7:55
  • the image is not visible, can it be fixed ?
    – user104369
    Apr 18, 2022 at 8:00
  • 1
    @Devhs Added image yes sure will share with you wait for some time I have added beforeSave in Backend Model File.
    – Prits
    Apr 18, 2022 at 8:00
  • 1
    Yes For Preview will look into it.
    – Prits
    Apr 18, 2022 at 8:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.