Question

I am following the answer to creating a table with dropdown in Store>Configuration.

Its looks good but not storing my selected dropdown value in core_config_data table.

currently its storing null array, if I remove dropdown and add text field than its working completely fine and also store data in database, so I think I made some mistake for creating dropdown.

Here is my code:

File: system.xml

    <field id="template" translate="label" sortOrder="5" showInDefault="1" showInWebsite="1" showInStore="1">
           <label>Select Template</label>
           <frontend_model>Vendor\Module\Block\Adminhtml\Form\Field\Template</frontend_model>
           <backend_model>Magento\Config\Model\Config\Backend\Serialized\ArraySerialized</backend_model>
    </field>

File: Template.php

class Template extends AbstractFieldArray
{
  protected $_itemRenderer;

  protected function _prepareToRender()
  {
    $this->addColumn(
        'deliverydays',
        [
            'label' => __('Delivery Days'),
            'readonly'=>'readonly',
            'renderer' => $this->_getRenderer()
        ]
    );
    $this->_addAfter = false;
    $this->_addButtonLabel = __('Add More');
  }

  protected function _getRenderer()
  {
    $this->_itemRenderer = $this->getLayout()->createBlock(
        \Vendor\Module\Block\Adminhtml\Form\Field\Options::class, '',
        array('is_render_to_js_template' => true)
    );
    return $this->_itemRenderer;
  }

File: Options.php

class Options extends Select
{
/**
 * @var \Magento\Eav\Model\Config
 */
protected $_eavConfig;

public function __construct(Context $context,
                            \Magento\Eav\Model\Config $eavConfig,
                            array $data = [])
{
    parent::__construct($context, $data);
    $this->_eavConfig = $eavConfig;
}

public function _toHtml()
{
    $html = '<select>';
            foreach ($this->attributeOptions() as $column):
    $html .= '<option value="'.$column.'">'.$column.'</option>';
            endforeach;
    $html .= '</select>';
    return $html;
}

public function setInputName($value)
{
    return $this->setName($value);
}

  public function attributeOptions(){
    $attributeCode = "delivery_days";
    $attribute = $this->_eavConfig->getAttribute('catalog_product', $attributeCode);
    $options = $attribute->getSource()->getAllOptions();
    $attrValues = [];
    foreach ($options as $option) {
        if ($option['value'] > 0) {
            $attrValues[] = $option['label']; //->getText(); //use '->getText' if attribute is system generated
        }
    }
    return $attrValues;
  }
}
Was it helpful?

Solution 2

I search in core files, you can see similar functionalities in:

Magento\CatalogInventory\Block\Adminhtml\Form\Field\Minsaleqty

File: Template.php

protected $_itemRenderer;

  protected function _prepareToRender()
  {
    $this->addColumn(
        'dayoption',
        [
            'label' => __('Delivery Days'),
            'readonly'=>'readonly',
            'renderer' => $this->_getRenderer()
        ]
    );
    $this->_addAfter = false;
    $this->_addButtonLabel = __('Add More');
  }

  protected function _getRenderer()
  {
    $this->_itemRenderer = $this->getLayout()->createBlock(
        \Vendor\Module\Block\Adminhtml\Form\Field\Options::class, '',
        ['data' => ['is_render_to_js_template' => true]]
    );
    $this->_itemRenderer->setClass('option_group_select');
    return $this->_itemRenderer;
  }

File: Option.php

use Magento\Framework\View\Element\Context;
use Magento\Framework\View\Element\Html\Select;

class Options extends Select
{
/**
 * @var \Magento\Eav\Model\Config
 */
protected $_eavConfig;
/**
 *
 * @var array
 */
private $_attributeGroups;

public function __construct(Context $context,
                            \Magento\Eav\Model\Config $eavConfig,
                            array $data = [])
{
    parent::__construct($context, $data);
    $this->_eavConfig = $eavConfig;
}

public function setInputName($value)
{
    return $this->setName($value);
}

public function _attributeOptions(){
    if ($this->_attributeGroups === null) {
        $this->_attributeGroups = [];

        $attributeCode = "delivery_days";
        $attribute = $this->_eavConfig->getAttribute('catalog_product', $attributeCode);
        $options = $attribute->getSource()->getAllOptions();
        $attrValues = [];
        foreach ($options as $option) {
            if ($option['value'] > 0) {
                $this->_attributeGroups[$option['label']] = $option['label'];
            }
        }
    }
    return $this->_attributeGroups;
}

/**
 * Render block HTML
 *
 * @return string
 */
  public function _toHtml()
  {
    if (!$this->getOptions()) {
        foreach ($this->_attributeOptions() as $item) {
            $this->addOption($item, addslashes($item));
        }
    }
    return parent::_toHtml();
  }      
}

OTHER TIPS

try this

        <field id="template"
               translate="label"
               type="select"
               sortOrder="5"
               showInDefault="1"
               showInWebsite="1"
               showInStore="1">
            <label>Select Template</label>
            <source_model>Vendor\Module\Model\Config\Source\Template</source_model>
        </field>

path: Vendor\Module\Model\Config\Source

Template.php

<?php

namespace Vendor\Module\Model\Config\Source;

use Magento\Framework\Data\OptionSourceInterface;

class Template implements OptionSourceInterface
{
    protected $_eavConfig;

    public function __construct(
        \Magento\Eav\Model\Config $eavConfig
    ) {
        $this->_eavConfig = $eavConfig;
    }
    public function getOptionArray()
    {
        $attributeCode = "delivery_days";
        $attribute = $this->_eavConfig->getAttribute('catalog_product', $attributeCode);
        $options = $attribute->getSource()->getAllOptions();
        $selectoptions = [];
        $i = 0;
        foreach ($options as $option) {
                     $selectoptions[$i] = $option->getText();
                     $i++;
        }
        return $selectoptions;
    }
    public function getAllOptions()
    {
        $res = $this->getOptions();
        array_unshift($res, ['value' => '', 'label' => '']);
        return $res;
    }
    public function getOptions()
    {
        $res = [];
        foreach ($this->getOptionArray() as $index => $value) {
            $res[] = ['value' => $index, 'label' => $value];
        }
        return $res;
    }
    public function toOptionArray()
    {
        return $this->getOptions();
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with magento.stackexchange
scroll top