1

I found one similar solution that almost does what I want.
DateTimePicker System.xml

I have implemented its code and was able to display a DateTime Picker in my admin configuration. However, I would like to implement a Time Range Picker but I don't need a UI component way of implementing it.

1

If you wish to add time from/to elements as a slider, you can customize an element frontend model and add your own template.

How it will be looking

Here is my example (ported from the regular form to the store configuration section):

Field in the system.xml:

<field id="delivery_time" translate="label comment" type="text" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="1" canRestore="1">
    <label>Delivery Time</label>
    <frontend_model>MageWorx\ExampleConfig\Model\Config\FrontendModel\DeliveryTime</frontend_model>
</field>

Note: real values will be stored with the delivery_time_from and delivery_time_to indexes.

Frontend model, where I have replaced the default output of the element:

<?php

namespace MageWorx\ExampleConfig\Model\Config\FrontendModel;


class DeliveryTime extends \Magento\Config\Block\System\Config\Form\Field
{
    /**
     * Retrieve element HTML markup
     *
     * @param \Magento\Framework\Data\Form\Element\AbstractElement $element
     * @return string
     * @throws \Magento\Framework\Exception\LocalizedException
     */
    protected function _getElementHtml(\Magento\Framework\Data\Form\Element\AbstractElement $element)
    {
        $renderer = $this->getLayout()->createBlock(
            'MageWorx\ExampleConfig\Block\TimeSlider'
        );
        $renderer->setElement($element);

        return $renderer->toHtml();
    }
}

here we just using a block MageWorx\ExampleConfig\Block\TimeSlider instead of general render.

And here is the block with template (where slider was defined):

<?php

namespace MageWorx\ExampleConfig\Block;

use Magento\Framework\Data\Form\Element\AbstractElement;

/**
 * Class TimeSlider
 */
class TimeSlider extends \Magento\Framework\View\Element\Template implements
    \Magento\Framework\Data\Form\Element\Renderer\RendererInterface,
    \Magento\Widget\Block\BlockInterface
{

    const TIME_NAME_FROM = 'groups[main][fields][delivery_time_from][value]';
    const TIME_NAME_TO   = 'groups[main][fields][delivery_time_to][value]';

    /**
     * Form element which re-rendering
     *
     * @var \Magento\Framework\Data\Form\Element\Fieldset
     */
    protected $element;

    /**
     * @var string
     */
    protected $_template = 'MageWorx_ExampleConfig::form/renderer/timeslider.phtml';

    /**
     * @var string
     */
    protected $_htmlId = 'time-range';

    /**
     * Retrieve an element
     *
     * @return \Magento\Framework\Data\Form\Element\Fieldset
     */
    public function getElement()
    {
        return $this->element;
    }

    /**
     * Set an element
     *
     * @param AbstractElement $element
     * @return $this
     */
    public function setElement(\Magento\Framework\Data\Form\Element\AbstractElement $element)
    {
        $this->element = $element;

        return $this;
    }

    /**
     * Render element
     *
     * @param AbstractElement $element
     * @return string
     */
    public function render(AbstractElement $element)
    {
        $this->element = $element;

        return $this->toHtml();
    }

    /**
     * @return string
     */
    public function getHtmlId()
    {
        return $this->_htmlId;
    }

    /**
     * @return string
     */
    public function getNameFrom()
    {
        return self::TIME_NAME_FROM;
    }

    /**
     * @return string
     */
    public function getNameTo()
    {
        return self::TIME_NAME_TO;
    }

    /**
     * @param int $minutes
     * @return string
     */
    public function minutesToTime($minutes)
    {
        $hours   = floor($minutes / 60);
        $minutes = $minutes % 60;
        $part    = $hours >= 12 ? 'PM' : 'AM';

        return sprintf('%02d:%02d %s', $hours, $minutes, $part);
    }

    /**
     * @return string
     * @throws \Magento\Framework\Exception\ValidatorException
     */
    protected function _toHtml()
    {
        if (!$this->getTemplate()) {
            return '';
        }

        return $this->fetchView($this->getTemplateFile());
    }
}

Note: you should change values of the constants TIME_NAME_FROM and TIME_NAME_TO to own ones, according your definition in the system.xml.

Template:

<?php

/** @var MageWorx\ExampleConfig\Block\TimeSlider $block */
$element = $block->getElement();
$form = $element->getForm();
/** @var \Magento\Config\Block\System\Config\Form $parentForm */
$parentForm = $form->getParent();
$timeFrom = $parentForm->getConfigValue('example_config/main/delivery_time_from');;
$timeTo = $parentForm->getConfigValue('example_config/main/delivery_time_to');;
?>
<div id="time-range" class="field field-time_range">
    <label class="label" style="white-space: normal;">
        <?php echo __('Time Range: ');?>
        <span class="slider-time">
            <?php echo $block->minutesToTime($timeFrom);?>
        </span>
        <?php echo ' - '; ?>
        <span class="slider-time2">
            <?php echo $block->minutesToTime($timeTo);?>
        </span>
    </label>
    <div class="sliders_step1 control">
        <div id="slider-range"></div>
        <input type="hidden"
               name="<?php echo $block->getNameFrom();?>"
               value="<?php echo $timeFrom?>""
            />
        <input type="hidden"
               name="<?php echo $block->getNameTo();?>"
               value="<?php echo $timeTo?>""
            />
    </div>
</div>
<script type="text/javascript">
    require(['jquery', 'jquery/ui'], function($){
        $("#slider-range").slider({
            range: true,
            min: 0,
            max: 1440,
            step: 15,
            values: [<?php echo $timeFrom?>, <?php echo $timeTo?>],
            slide: function (e, ui) {
                var hours1 = Math.floor(ui.values[0] / 60);
                var minutes1 = ui.values[0] - (hours1 * 60);

                if (hours1.length == 1) hours1 = '0' + hours1;
                if (minutes1.length == 1) minutes1 = '0' + minutes1;
                if (minutes1 == 0) minutes1 = '00';
                if (hours1 >= 12) {
                    if (hours1 == 12) {
                        hours1 = hours1;
                        minutes1 = minutes1 + " PM";
                    } else {
                        hours1 = hours1 - 12;
                        minutes1 = minutes1 + " PM";
                    }
                } else {
                    hours1 = hours1;
                    minutes1 = minutes1 + " AM";
                }
                if (hours1 == 0) {
                    hours1 = 12;
                    minutes1 = minutes1;
                }


                $('.slider-time').html(hours1 + ':' + minutes1);

                var hours2 = Math.floor(ui.values[1] / 60);
                var minutes2 = ui.values[1] - (hours2 * 60);

                if (hours2.length == 1) hours2 = '0' + hours2;
                if (minutes2.length == 1) minutes2 = '0' + minutes2;
                if (minutes2 == 0) minutes2 = '00';
                if (hours2 >= 12) {
                    if (hours2 == 12) {
                        hours2 = hours2;
                        minutes2 = minutes2 + " PM";
                    } else if (hours2 == 24) {
                        hours2 = 11;
                        minutes2 = "59 PM";
                    } else {
                        hours2 = hours2 - 12;
                        minutes2 = minutes2 + " PM";
                    }
                } else {
                    hours2 = hours2;
                    minutes2 = minutes2 + " AM";
                }

                $('.slider-time2').html(hours2 + ':' + minutes2);
                $('[name="<?php echo $block->getNameFrom();?>"]').val(ui.values[0]);
                $('[name="<?php echo $block->getNameTo();?>"]').val(ui.values[1]);
            }
        });
    });
</script>

That's all. Based on this example you can modify code to add base features like a use global value etc.

Here is full code on the GitHub.

PS: Example partially taken from the Shipping Suite Ultimate Extension by MageWorx (where that kind of slider used in the form).

PPS: in the example time stored in the database in minutes, like 120 => 2:00 AM.

  • tried to install the module from github but it doesn't work – fmsthird Apr 15 at 6:23
  • @magefms What exactly does not work? This code just a example, so need to be rewritten as per your needs. – Siarhey Uchukhlebau Apr 16 at 7:35
  • it's okay I fixed it already and now it is working using my own method. I did not use the model because I think it is not necessary. Thank you for your help. – fmsthird Apr 16 at 7:38
  • @magefms I tried but got this error " Uncaught TypeError: Cannot read property 'addClass' of undefined". have you any clue for that ? – Sarfaraj Sipai May 3 at 13:31
  • @Sarfaraj were you able to solve your issue? – fmsthird May 14 at 8:30
3

I would suggest to use the same way magento uses for saving time.

In your admin panel, goto

Stores -> Configuration -> Advanced -> System -> Scheduled Backup Settings

See the Start Time field.

enter image description here

You may use the same thing in your system.xml file. It seems more accurate.

Let me know if you need a code sample for that. I have used the same in one of my module.

etc/adminhtml/system.xml

<field id="opening_time" translate="label" type="time" showInDefault="1" showInWebsite="1" showInStore="1" sortOrder="40">
    <label>Opening Time</label>
</field>

Just add above field in system.xml and it will work as per magento standard. It will save time like 15,25,00. The type='time' makes it work. Thats it. No additional coding is needed.

  • can you include code for this one so that I can check – fmsthird Apr 10 at 7:50
  • Edited answer with the code. Please check. – Yash Shah Apr 10 at 7:54
  • okay, I will update you if it works – fmsthird Apr 10 at 7:54
  • 1
    THank you soo much – Waqar Ali Oct 24 at 12:26
1

You can follow steps below to show Datetime field in your custom module admin config section

step 1) Create system.xml under ***app/code/Vendor/Module/etc/adminFile:*

File : app/code/Vendor/MyModule/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="mycustom" translate="label" sortOrder="450">
            <label>My Custom Setting</label>
        </tab>
        <section id="mycustom" translate="label" type="text" sortOrder="100" showInDefault="1" showInWebsite="1" showInStore="1">
            <class>separator-top</class>
            <label>My Custom Setting</label>
            <tab>mycustom</tab>
            <resource>Magento_Checkout::config</resource>
            <group id="general" translate="label" type="text" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="1">
                <field id="mydate" translate="label" type="date" showInDefault="1" showInWebsite="1" showInStore="1">
                    <label>My Date Field</label>
                    <frontend_model>Vendor\MyModule\Block\Adminhtml\System\Config\DateTime</frontend_model>
                </field>
            </group>
        </section>
    </system>
</config>

step 2) Create the block DateTime.php under /app/code/Vendor/MyModule/Block/Adminhtml/System/Config/DateTime.php

File : /app/code/Vendor/MyModule/Block/Adminhtml/System/Config/DateTime.php

<?php

namespace Vendor\MyModule\Block\Adminhtml\System\Config;

class DateTime extends \Magento\Config\Block\System\Config\Form\Field
{

    protected $timezone;

    public function __construct(
        \Magento\Backend\Block\Template\Context $context,
        \Magento\Framework\Stdlib\DateTime\TimezoneInterface $timezone,
        array $data = []
    ) {
        $this->timezone = $timezone;
        parent::__construct($context, $data);
    }

    public function render(\Magento\Framework\Data\Form\Element\AbstractElement $element)
    {
        $element->setDateFormat($this->timezone->getDateFormat());
        $element->setTimeFormat($this->timezone->getTimeFormat());
        $element->setShowsTime(true);
        return parent::render($element);
    }
}

step 3: Run Following commands

sudo php bin/magento setup:di:compile
sudo php bin/magento cache:flush

step 4: Check your custom module admin config section for newly added datetime config field.

enter image description here

  • Thanks for the answer bro, but I have done that already, please review my requirement, I need time picker only. – fmsthird Apr 10 at 7:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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