Magento – Add Date Picker and/or Validation To System Config Form Field Array

adminconfigurationcore-config-datadatedatepicker

I'm building a module to handle business hours for a physical retail store. The idea is to have configurable fields for the business hours on each day of the week so they can be changed seasonally. In additional to the regular, weekly hours changing, sometimes there are one off exceptions such as closing early or being closed on a specific date. To handle this I need to allow a user to enter a date, the special hours for that day, and a note for the reason. On the front end these exceptions will be displayed only until the date has passed, and on the specified date they will be displayed as today's hours.

I've started building this using Magento's system configuration. Here are the fields I've created in my system.xml:

<fields>
    <monday translate="label">
        <label>Monday</label>
        <frontend_type>text</frontend_type>
        <sort_order>1</sort_order>
        <show_in_default>1</show_in_default>
        <show_in_website>1</show_in_website>
        <show_in_store>1</show_in_store>
    </monday>
    <tuesday translate="label">   <!-- same nodes here --> </tuesday>
    <wednesday translate="label"> <!-- same nodes here --> </wednesday>
    <thursday translate="label">  <!-- same nodes here --> </thursday>
    <friday translate="label">    <!-- same nodes here --> </friday>
    <saturday translate="label">  <!-- same nodes here --> </saturday>
    <sunday translate="label">    <!-- same nodes here --> </sunday>
    <exceptions translate="label">
        <label></label>
        <frontend_model>gxcore/adminhtml_system_config_hoursexceptions</frontend_model>
        <backend_model>adminhtml/system_config_backend_serialized_array</backend_model>
        <sort_order>8</sort_order>
        <show_in_default>1</show_in_default>
        <show_in_website>1</show_in_website>
        <show_in_store>1</show_in_store>
        <comment>For dates when the store is closed or has irregular hours</comment>
    </exceptions>
</fields>

Here is the HoursException class used as a fontend_model:

<?php
class Gearx_GxCore_Block_Adminhtml_System_Config_HoursExceptions extends Mage_Adminhtml_Block_System_Config_Form_Field_Array_Abstract
{
    public function __construct()
    {
        $this->addColumn('date', array(
                'label' => Mage::helper('adminhtml')->__('Date'),
                'style' => 'width:80px',
        ));
        $this->addColumn('hours', array(
                'label' => Mage::helper('adminhtml')->__('Hours'),
                'style' => 'width:110px',
        ));
        $this->addColumn('note', array(
                'label' => Mage::helper('adminhtml')->__('Note'),
                'style' => 'width:200px',
        ));
        $this->_addAfter = false;
        $this->_addButtonLabel = Mage::helper('adminhtml')->__('Add Exception');
        parent::__construct();
    }
}

And here is what the user sees in the Admin:

enter image description here

This all works fine, but the date is stored as a string in the exceptions serialized array and there is no input validation. This means users could enter a date in the wrong format and things wouldn't work as expected.

So my question: Is there a way to specify this field as a 'date' data type or put any sort of validation on it?

I've seen that it's possible to use the Magento date picker widget on a standard system configuration field by making a custom frontend_model class. Here's some example code:

class Arvtour_Tour_Block_Adminhtml_System_Config_Date extends Mage_Adminhtml_Block_System_Config_Form_Field
{
    protected function _getElementHtml(Varien_Data_Form_Element_Abstract $element)
    {
        $date = new Varien_Data_Form_Element_Date;
        $format = Mage::app()->getLocale()->getDateFormat(Mage_Core_Model_Locale::FORMAT_TYPE_SHORT);

        $data = array(
            'name'      => $element->getName(),
            'html_id'   => $element->getId(),
            'image'     => $this->getSkinUrl('images/grid-cal.gif'),
        );
        $date->setData($data);
        $date->setValue($element->getValue(), $format);
        $date->setFormat(Mage::app()->getLocale()->getDateFormat(Mage_Core_Model_Locale::FORMAT_TYPE_SHORT));
        $date->setForm($element->getForm());

        return $date->getElementHtml();
    }
}

I've already set up a custom frontend_model, but it's a form field array, not a single field. So I guess I'd need to combine them somehow and I'm not sure that's even possible. Maybe I'm trying to do too much in system configuration and there's a better way to do this entirely. Any input would be much appreciated.

Best Answer

I'd really recommend you use separate "from" and "to" fields. For fields like this:

<monday translate="label">
    <label>Monday</label>
    <frontend_type>text</frontend_type>
    <sort_order>1</sort_order>
    <show_in_default>1</show_in_default>
    <show_in_website>1</show_in_website>
    <show_in_store>1</show_in_store>
</monday>

You should be able to add a <validate>validate-date</validate> field. A list of different validations can be found in the source code of /js/prototype/validation.js.