1

I need to add option to select multiple dates in system configure. I can add single date input field in system configure. but I doesn't have any idea about to add multi date picker in system configure.

system.xml file

<?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>
        <section id="carriers" translate="label" type="text" sortOrder="320" showInDefault="1" showInWebsite="1" showInStore="1">
            <group id="customshippingmethod" translate="label" type="text" sortOrder="900" showInDefault="1" showInWebsite="1" showInStore="1">
                <label>Custom Shipping Method</label>
                <field id="active" translate="label" type="select" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="0" canRestore="1">
                    <label>Enabled</label>
                    <source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
                </field>
                <field id="from_date" translate="label" type="date" sortOrder="15" showInDefault="1" showInWebsite="1"
                  showInStore="1">
                    <label>From</label>
                    <!-- Here we pass class where we create date picker-->
                    <frontend_model>Vendor\ModuleName\Block\DatePicker</frontend_model>
                </field>
            </group>
        </section>
    </system>
</config>

Vendor\ModuleName\Block\DatePicker File

<?php
namespace Vendor\ModuleName\Block;

class DatePicker extends \Magento\Config\Block\System\Config\Form\Field
{
   public function render(\Magento\Framework\Data\Form\Element\AbstractElement $element)
   {
       $element->setDateFormat(\Magento\Framework\Stdlib\DateTime::DATE_INTERNAL_FORMAT);
       $element->setTimeFormat('HH:mm:ss'); //set date and time as per your need
       $element->setShowsTime(true);
       return parent::render($element);
   }
}

see below Image to understand exactly what I have to achieve

enter image description here

2 Answers 2

1

Add in your system.xml

<field id="dynamic_field_holidays" translate="label" sortOrder="4" showInDefault="1" showInWebsite="1" showInStore="1">
               <label>Holidays/Exclude Days/Blackout Days</label> 
     
     <backend_model>Vendor\Module\Block\Adminhtml\Config\Backend\Datepicker</backend_model>
            <frontend_model>Vendor\Module\Block\Adminhtml\Datepicker</frontend_model>
</field>

Create Datepicker.php file at Vendor\Module\Block\Adminhtml\Config\Backend

<?php

namespace Vendor\Module\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 Datepicker 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);
        }
    }
}

Create Datepicker.php file at Vendor\Module\Block\Adminhtml

<?php

namespace Vendor\Module\Block\Adminhtml;

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 Datepicker extends AbstractFieldArray
{
    private $holidaysRenderer;
    private $dateRenderer;

    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:200px'
            ]
        );

        $this->addColumn(
            'date_title',
            [
                'label' => __('Content'),
                'class' => 'required-entry',
                'style' => 'width:300px',
            ]
        );

        $this->_addAfter = false;
        $this->_addButtonLabel = __('MoreAdd');
    }

    protected function _prepareArrayRow(DataObject $row): void
    {
        $options = [];
        $row->setData('option_extra_attrs', $options);
    }

    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;
    }
}
1
  • Thank you for solution. your solution is also worked. you answer & my answer almost same. just difference is using my answer it save date in standard Y-m-d format. & using your answer it save the date in d/m/Y format. Jul 20, 2022 at 5:57
0

I found solution. I share that solution with community I hope this one is helped to you.

system.xml file

<field id="exclude_days" translate="label" sortOrder="20" showInDefault="1" showInWebsite="1" showInStore="0">
    <label>Exclude Days</label>
    <frontend_model>Vendor\ModuleName\Block\System\Config\Form\Field\ExcludeDaysMultipleFields</frontend_model>
    <backend_model>Vendor\ModuleName\Model\Config\Backend\ExcludeDaysMultipleFields</backend_model>
</field>

ExcludeDaysMultipleFields fronend Model created at Vendor\ModuleName\Block\System\Config\Form\Field path

<?php
 
namespace Vendor\ModuleName\Block\System\Config\Form\Field;

use Magento\Config\Block\System\Config\Form\Field\FieldArray\AbstractFieldArray;
 
class ExcludeDaysMultipleFields extends AbstractFieldArray
{
    protected function _prepareToRender()
    {
        $this->addColumn('date', ['label' => __('Date'), 'class' => 'js-date-excluded-datepicker']);
        $this->addColumn('content', ['label' => __('content'), 'class' => 'required-entry']);        
        $this->_addAfter = false;
        $this->_addButtonLabel = __('Add Date');

        parent::_prepareToRender();
    }


    /**
     * Prepare existing row data object
     * Convert backend date format "2022-01-12" to front format "12/01/2022"
     *
     * @param \Magento\Framework\DataObject $row
     * @return void
     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
     */
    protected function _prepareArrayRow(\Magento\Framework\DataObject $row)
    {
        $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;
    }
}

ExcludeDaysMultipleFields backend model created at Vendor\ModuleName\Model\Config\Backend path

<?php

namespace Vendor\ModuleName\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 ExcludeDaysMultipleFields extends \Magento\Config\Model\Config\Backend\Serialized\ArraySerialized
{
    /**
     * Json Serializer
     *
     * @var SerializerInterface
     */
    protected $serializer;

    /**
     * ShippingMethods constructor
     *
     * @param SerializerInterface $serializer
     * @param Context $context
     * @param Registry $registry
     * @param ScopeConfigInterface $config
     * @param TypeListInterface $cacheTypeList
     * @param AbstractResource|null $resource
     * @param AbstractDb|null $resourceCollection
     * @param array $data
     */
    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);
    }

    /**
     * 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 {
                $date = \DateTime::createFromFormat('d/m/Y', $data['date']);
                $value[$key] = [
                    'date' => $date->format('Y-m-d'),
                    'content' => $data['content'],
                ];
            } catch (\Exception $e) {
                // Just skipping error values
            }
        }
        $encodedValue = $this->serializer->serialize($value);
        $this->setValue($encodedValue);
        return parent::beforeSave();
    }
}

Output

output image

1

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.

Not the answer you're looking for? Browse other questions tagged or ask your own question.