4

I want to create an admin config with "exception dates".

Since the number of these dates can vary, I cannot just put a constant number of input fields in the config.

Is there a way to automatically add more fields or have a button to add extra fields? Then perhaps collecting the values into an array...

1
  • I followed the above answer as it is for my module, everything is working fine, even saved values are also storing in database, but the thing is when I reopen it in admin side later the selected dropdown is not showing on the screen. Why is it so? Commented Dec 1, 2018 at 9:50

1 Answer 1

4

To add an "Add field" button to you config field, you can use this:

app/code/POOL/My/Module/etc/system.xml

<delay_by_country translate="label">
    <label>Email delay per country</label>
    <frontend_model>mx_custom_emails/adminhtml_config_countryDays</frontend_model>
    <backend_model>adminhtml/system_config_backend_serialized_array</backend_model>
    <sort_order>110</sort_order>
    <show_in_default>1</show_in_default>
    <show_in_website>1</show_in_website>
    <show_in_store>0</show_in_store>
    <depends><enabled>1</enabled></depends>
</delay_by_country>

See <frontend_model> and <backend_model>. Frontend model is responsable for you system config output and backend model adminhtml/system_config_backend_serialized_array to store data as serialized array.

For set frontend model you have to create an new block class to generate the field form.

app\code\local\Mx\CustomEmails\Block\Adminhtml\Config\CountryDays.php

class Mx_CustomEmails_Block_Adminhtml_Config_CountryDays extends Mage_Adminhtml_Block_System_Config_Form_Field_Array_Abstract
{
    protected $_itemRenderer;

    /**
     * Fix for ignored "depends enabled"
     * See: https://magento.stackexchange.com/questions/15500/configuration-depends-with-front-and-backend-model
     */
    public function _toHtml()
    {
        return '<div id="' . $this->getElement()->getId(). '">' . parent::_toHtml() . '</div>';
    }

    public function _prepareToRender()
    {
        $this->addColumn('country_id', array(
            'label' => Mage::helper('mx_custom_emails')->__('Country'),
            'renderer' => $this->_getRenderer(),
        ));
        $this->addColumn('email_delay', array(
            'label' => Mage::helper('mx_custom_emails')->__('Email Delay in Days'),
            'style' => 'width:100px',
            'class' => 'validate-zero-or-greater input-text',
        ));

        $this->_addAfter = false;
        $this->_addButtonLabel = Mage::helper('mx_custom_emails')->__('Add');
    }

    protected function _getRenderer()
    {
        if (!$this->_itemRenderer) {
            $this->_itemRenderer = $this->getLayout()->createBlock(
                'mx_custom_emails/adminhtml_config_form_field_country',
                '',
                array('is_render_to_js_template' => true)
            );
        }
        return $this->_itemRenderer;
    }

    protected function _prepareArrayRow(Varien_Object $row)
    {
        $row->setData(
            'option_extra_attr_' . $this->_getRenderer()
                ->calcOptionHash($row->getData('country_id')),
            'selected="selected"'
        );
    }
}

Within the _getRenderer() method you define another block class that's responable for rendering a column (in my case a dropdown for all countries)

app\code\local\Mx\CustomEmails\Block\Adminhtml\Config\Form\Field\Country.php

class Mx_CustomEmails_Block_Adminhtml_Config_Form_Field_Country extends Mage_Core_Block_Html_Select
{
    /**
     * Prepare HTML output
     *
     * @return Mage_Core_Block_Html_Select
     */
    public function _toHtml()
    {
        $options = Mage::getSingleton('adminhtml/system_config_source_country')
            ->toOptionArray();
        foreach ($options as $option) {
            $this->addOption($option['value'], $option['label']);
        }

        return parent::_toHtml();
    }

    /**
     * Set field name
     *
     * @param string $value
     */
    public function setInputName($value)
    {
        return $this->setName($value);
    }
}

To access the serialized config data you can do this (just as example from an observer, you have to replace config path and add your logic):

$delay = Mage::getStoreConfig('sales_email/mx_custom_emails/delay_by_country');
# important line
$delay = unserialize($delay);
if (is_array($delay) || sizeof($delay)) {
    $shippingAddressCountryId = $order->getShippingAddress()->getCountryId();
    # important lines
    foreach ($delay as $row) {
        if ($shippingAddressCountryId == $row['country_id']) {
            return $row['email_delay'];
        }
    }
}

Finally cou have to create your modules XML file and a config.xml where you define helper (for translation), block and model classes:

app/code/POOL/My/Module/etc/config.xml

<blocks>
    <mx_custom_emails>
        <class>Mx_CustomEmails_Block</class>
    </mx_custom_emails>
</blocks>
<helpers>
    <mx_custom_emails>
        <class>Mx_CustomEmails_Helper</class>
    </mx_custom_emails>
</helpers>
<models>
    <mx_custom_emails>
        <class>Mx_CustomEmails_Model</class>
    </mx_custom_emails>
</models>

You can also create fields/groups and sections dynamically ... therefor i recommend reading Create system config section with dynamic number of fields @ Marius blog.

1
  • 1
    Oh wow, thanks for the comprehensive answer! Commented Jul 9, 2017 at 5:29

Your Answer

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

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