8

enter image description here

This image what I already have. I have to make second column as multiselect. How to achieve this? This should be configuration field.

4

2 Answers 2

17

Create Field class like below copied from magento dev docs

<?php
namespace Vendor\Module\Block\Adminhtml\Form\Field;

use Magento\Config\Block\System\Config\Form\Field\FieldArray\AbstractFieldArray;
use Magento\Framework\DataObject;
use Magento\Framework\Exception\LocalizedException;
use Vendor\Module\Block\Adminhtml\Form\Field\TaxColumn;

/**
 * Class Ranges
 */
class Ranges extends AbstractFieldArray
{
    /**
     * @var TaxColumn
     */
    private $taxRenderer;

    /**
     * Prepare rendering the new field by adding all the needed columns
     */
    protected function _prepareToRender()
    {
        $this->addColumn('from_qty', ['label' => __('From'), 'class' => 'required-entry']);
        $this->addColumn('to_qty', ['label' => __('To'), 'class' => 'required-entry']);
        $this->addColumn('price', ['label' => __('Price'), 'class' => 'required-entry']);
        $this->addColumn('tax', [
            'label' => __('Tax'),
            'renderer' => $this->getTaxRenderer()
        ]);
        /* Multiselect code */
        $this->addColumn('country', [
            'label' => __('Country'),
            'renderer' => $this->getCountryRenderer(),
            'extra_params' => 'multiple="multiple"'
        ]);
        $this->_addAfter = false;
        $this->_addButtonLabel = __('Add');
    }

    /**
     * Prepare existing row data object
     *
     * @param DataObject $row
     * @throws LocalizedException
     */
    protected function _prepareArrayRow(DataObject $row): void
    {
        $options = [];

        $tax = $row->getTax();
        if ($tax !== null) {
            $options['option_' . $this->getTaxRenderer()->calcOptionHash($tax)] = 'selected="selected"';
        }

        $countries = $row->getCountry();
        if(count($countries) > 0){
            foreach ($countries as $country) {
                $options['option_' . $this->getCountryRenderer()->calcOptionHash($country)]
                    = 'selected="selected"';
            }
        }

        $row->setData('option_extra_attrs', $options);
    }

    /**
     * @return TaxColumn
     * @throws LocalizedException
     */
    private function getTaxRenderer()
    {
        if (!$this->taxRenderer) {
            $this->taxRenderer = $this->getLayout()->createBlock(
                TaxColumn::class,
                '',
                ['data' => ['is_render_to_js_template' => true]]
            );
        }
        return $this->taxRenderer;
    }

    /* Multiselect renderer for countries */
    private function getCountryRenderer()
    {
        if (!$this->countryRenderer) {
            $this->countryRenderer = $this->getLayout()->createBlock(
                \Vendor\Module\Block\Adminhtml\Form\Field\CountryColumn::class,
                '',
                ['data' => ['is_render_to_js_template' => true]]
            );
        }
        return $this->countryRenderer;
    }
}

Create CountryColumn class under

app/code/Vendor/Module/Block/Adminhtml/Form/Field/CountryColumn.php

with below content

<?php
declare(strict_types=1);

namespace Vendor\Module\Block\Adminhtml\Form\Field;

use Magento\Braintree\Helper\Country;
use Magento\Framework\View\Element\Context;
use Magento\Framework\View\Element\Html\Select;

class CountryColumn extends Select
{
    private $countryHelper;

    public function __construct(
        Context $context,
        Country $countryHelper,
        array $data = []
    ) {
        parent::__construct($context, $data);
        $this->countryHelper = $countryHelper;
    }

    public function setInputName($value)
    {
        return $this->setName($value . '[]');
    }

    public function _toHtml(): string
    {
        if (!$this->getOptions()) {
            $this->setOptions($this->countryHelper->getCountries());
        }
        $this->setExtraParams('multiple="multiple"');
        return parent::_toHtml();
    }
}
3
  • 2
    Man, you are wizard, thank you very much! Dec 26, 2019 at 15:48
  • 2
    good solution. (y) Dec 27, 2019 at 6:01
  • I have implemented this, this is saving data to databse but not able to see it selected on load. Can you suggest me? [option_extra_attrs] => Array ( [option_4200685455] => selected="selected" ) I get this extra in $row array. but not showing as selected.
    – Dolly
    Apr 4, 2023 at 19:37
0

Adding $this->setExtraParams('multiple="multiple"'); is not enough In your frontend_model, you need to set the option when there is array.

protected function _prepareArrayRow(DataObject $row): void { $options = [];

    $region = $row->getRegion();


    if (is_array($region) && count($region) > 0) {
        foreach ($region as $r) {
            $options['option_' . $this->getRegionRender()->calcOptionHash($r)]
                = 'selected="selected"';
        }
    } else if ($region !== null) {
        $options['option_' . $this->getRegionRender()->calcOptionHash($region)] = 'selected="selected"';
    }




    $row->setData('option_extra_attrs', $options);
}

ANd in your column render, you need to set the html input name as array:

public function setInputName($value) { return $this->setName($value . '[]'); }

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.