2

I have added a basic admin form field in system.xml as follows:

<field id="do_something" translate="label comment" type="checkbox" sortOrder="5" showInDefault="1" showInWebsite="1" showInStore="1">
    <label>Do something?</label>
    <comment>Do we want to do something?</comment>
</field>

The field renders correctly, and saves with no errors, and a row is added to core_config_data, but the value is always NULL regardless of whether the box was checked or not.

What am I missing?

  • You can show your core_config_data with this path? And your code to get this value? – Khoa TruongDinh Aug 3 '16 at 16:03
  • I can see the NULL value in the database, I've not got as far as using it in my module. – James Aug 3 '16 at 16:16
  • I think we should use type="select", and then try to add Default Source. – Khoa TruongDinh Aug 3 '16 at 16:17
  • Changing the style of field can work for you? – Khoa TruongDinh Aug 4 '16 at 13:48
  • Thanks @KhoaTruongDinh that did work, but it doesn't answer my question unfortunately - anyone wanting a checkbox, instead of a clunky dropdown, is no closer to resolving this. – James Aug 4 '16 at 16:06
2

As far as I know, by default Magento, we cannot save the value of checkbox with a simple declaration of checkbox type in xml config. So, we need to create our own custom renderer for this config.

Create admin config: app/code/Vendor/YourModule/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="sample_tab" translate="label" sortOrder="1000">
            <label>Example tab config</label>
        </tab>
        <section id="sample_section" translate="label" type="text" sortOrder="100" showInDefault="1" showInWebsite="1" showInStore="1">
            <label>Example config section</label>
            <tab>sample_tab</tab>
            <resource>Vendor_YourModule::config</resource>
            <group id="general" translate="label" type="text" sortOrder="5" showInDefault="1" showInWebsite="1" showInStore="1">
                <label>General</label>
                <field id="do_something" translate="label" type="checkbox" sortOrder="5" showInDefault="1" showInWebsite="1" showInStore="1">
                    <label>Do something?</label>
                    <frontend_model>Vendor\YourModule\Block\Adminhtml\System\Config\Checkbox</frontend_model>
                    <comment>Do we want to do something?</comment>
                </field>
            </group>
        </section>
    </system>
</config>

Basically, our config declare a frontend model for rendering custom field.

Create frontend model block: app/code/Vendor/YourModule/Block/Adminhtml/System/Config/Checkbox.php

<?php

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

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

class Checkbox extends \Magento\Config\Block\System\Config\Form\Field
{
    const CONFIG_PATH = 'sample_section/general/do_something';

    protected $_template = 'Vendor_YourModule::system/config/checkbox.phtml';

    protected $_values = null;

    /**
     * Checkbox constructor.
     * @param \Magento\Backend\Block\Template\Context $context
     * @param array $data
     */
    public function __construct(
        \Magento\Backend\Block\Template\Context $context,
        array $data = []
    ) {
        parent::__construct($context, $data);
    }
    /**
     * Retrieve element HTML markup.
     *
     * @param AbstractElement $element
     *
     * @return string
     */
    protected function _getElementHtml(AbstractElement $element)
    {
        $this->setNamePrefix($element->getName())
            ->setHtmlId($element->getHtmlId());

        return $this->_toHtml();
    }

    public function getValues()
    {
        $values = [];
        $optionArray = \Vendor\YourModule\Model\Config\Source\Checkbox::toOptionArray();
        foreach ($optionArray as $value) {
            $values[$value['value']] = $value['label'];
        }
        return $values;
    }

    /**
     * Get checked value.
     * @param  $name
     * @return boolean
     */
    public function getIsChecked($name)
    {
        return in_array($name, $this->getCheckedValues());
    }
    /**
     *
     * Retrieve the checked values from config
     */
    public function getCheckedValues()
    {
        if (is_null($this->_values)) {
            $data = $this->getConfigData();
            if (isset($data[self::CONFIG_PATH])) {
                $data = $data[self::CONFIG_PATH];
            } else {
                $data = '';
            }
            $this->_values = explode(',', $data);
        }

        return $this->_values;
    }
}

Config source value: app/code/Vendor/YourModule/Model/Config/Source/Checkbox.php

<?php

namespace Vendor\YourModule\Model\Config\Source;

class Checkbox
{
    public static function toOptionArray()
    {
        return [['value' => 'checkbox', 'label'=>__('Do something?')]];
    }
}

app/code/Vendor/YourModule/view/adminhtml/templates/system/config/checkbox.phtml

<input type="hidden" name="<?php echo $this->getNamePrefix() ?>" value="" /><!-- this is send if nothing is checked -->
<ul class="checkboxes">
    <?php foreach ($this->getValues() as $name => $label): ?>
        <li>
            <input type="checkbox" value="<?php echo $name?>"
                   name="<?php echo $this->getNamePrefix() ?>[]"
                   id="<?php echo $this->getHtmlId() . '_' . $name ?>"
                <?php echo ($this->getIsChecked($name) ? ' checked="checked"' : '') ?>
            />
            <label for="<?php echo $this->getHtmlId() . '_' . $name ?>">
                <?php echo $label ?>
            </label>
        </li>
    <?php endforeach;?>
</ul>

Alternative solutions

--In your case, We can use type="select", and then try to add the Default Yesno Source.

<field id="do_something" translate="label" type="select" sortOrder="5" showInDefault="1" showInWebsite="1" showInStore="1">
    <label>Do something?</label>
    <source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
    <comment>Do we want to do something?</comment>
</field>

--Also use type="multiselect" if there are many values.

 <field id="do_something" translate="label" type="multiselect" sortOrder="5" showInDefault="1" showInWebsite="1" showInStore="1">
        <label>Do something?</label>
       <source_model>Vendor\YourModule\Model\Config\Source\Checkbox</source_model>
  </field>

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.