13

I have a custom entity in my magento 2 install.
And one of the fields in this entity is of type multiselect and contains the list of all countries.
I'm using the ui-components for my admin form.
Since there are about 200 records in the select, I don't want to have a multiselect field because it's not that easy to use.
So I created one of those fancy multiselects similar to the categories field in the add/edit product admin section.
It looks nicer, but I cannot set a default value to it.
Here is my configuration (notice the default config item):

<field name="affected_countries" formElement="select" component="Magento_Ui/js/form/element/ui-select" sortOrder="100">
    <argument name="data" xsi:type="array">
        <item name="config" xsi:type="array">
            <item name="source" xsi:type="string">article</item>
            <item name="filterOptions" xsi:type="boolean">true</item>
            <item name="chipsEnabled" xsi:type="boolean">true</item>
            <item name="disableLabel" xsi:type="boolean">true</item>
            <item name="default" xsi:type="string">RO,MD</item>
        </item>
    </argument>
    <settings>
        <elementTmpl>ui/grid/filters/elements/ui-select</elementTmpl>
        <dataType>text</dataType>
        <label translate="true">Affected Countries</label>
        <dataScope>affected_countries</dataScope>
        <componentType>field</componentType>
    </settings>
    <formElements>
        <select>
            <settings>
                <options class="Magento\Config\Model\Config\Source\Locale\Country"/>
            </settings>
        </select>
    </formElements>
</field>

It results into this:

And I'm expecting the 2 values I placed in the default field to be selected:

If I turn the element into a simple multiselect it works nicely.

<field name="affected_countries" formElement="multiselect" sortOrder="100">
    <argument name="data" xsi:type="array">
        <item name="config" xsi:type="array">
            <item name="source" xsi:type="string">article</item>
            <item name="default" xsi:type="string">RO,MD</item>
        </item>
    </argument>
    <settings>
        <dataType>text</dataType>
        <label translate="true">Affected Countries</label>
        <dataScope>affected_countries</dataScope>
    </settings>
    <formElements>
        <multiselect>
            <settings>
                <options class="Magento\Config\Model\Config\Source\Locale\Country"/>
            </settings>
        </multiselect>
    </formElements>
</field>

I tied with this format for the default setting

<item name="default" xsi:type="string">RO,MD</item>

and this one also:

<item name="default" xsi:type="array">
    <item name="MD" xsi:type="string">MD</item>
    <item name="RO" xsi:type="string">RO</item>
</item>

Also tried with the tag select and multiselect inside the formElements tag.
All of my tries ended up in failure.

Using the default setting in any other types of fields, as instructed here (text, select, date, ...) works nicely.

Any suggestion for the fancy selects? Something I missed?

Note: I know I can supply a default value in the data provider that populates the form, but I'm trying to avoid this as it looks ugly and it's not that extensible and not consistent with the rest of the fields.

11
  • did you try with the id of the options?
    – Adrian Z.
    Mar 29, 2018 at 8:34
  • MD and RO are the ids of the options. Like I said, it works with a normal multiselect using the same default values
    – Marius
    Mar 29, 2018 at 8:50
  • <items name="default" xsi:type="array"> </items> Mar 29, 2018 at 9:57
  • @IdhamChoudry I already tried that. It says so in the question.
    – Marius
    Mar 29, 2018 at 10:34
  • 1
    @LazyCoder take a look in my question at this <options class="Magento\Config\Model\Config\Source\Locale\Country"/>. You need a similar class that implements \Magento\Framework\Option\ArrayInterface and has a method called toOptionArray that returns an array with your values. each element from the array must look like this ['value' => ..., 'label' => ...]
    – Marius
    Apr 3, 2018 at 11:26

1 Answer 1

1

I worked for custom categories but in this method you have to provide countries data via database, take idea from this code and you may provide data from Db or Static Data by extending magento data, Hope it may helps

The xml code

    <field name="country_id">
    <argument name="data" xsi:type="array">
        <item name="options" xsi:type="object">Vendor\Module\Model\Config\Source\CountriesTree</item>
        <item name="config" xsi:type="array">
            <item name="label" xsi:type="string" translate="true">Country</item>
            <item name="formElement" xsi:type="string">select</item>
            <item name="component" xsi:type="string">Magento_Ui/js/form/element/ui-select</item>
            <item name="elementTmpl" xsi:type="string">ui/grid/filters/elements/ui-select</item>
            <item name="dataScope" xsi:type="string">category_id</item>
            <item name="filterOptions" xsi:type="boolean">true</item>
            <item name="chipsEnabled" xsi:type="boolean">true</item>
            <item name="showCheckbox" xsi:type="boolean">true</item>
            <item name="disableLabel" xsi:type="boolean">true</item>
            <item name="multiple" xsi:type="boolean">true</item>
            <item name="levelsVisibility" xsi:type="number">1</item>
            <item name="sortOrder" xsi:type="number">30</item>
            <item name="validation" xsi:type="array">
                <item name="required-entry" xsi:type="boolean">false</item>
            </item>
            <item name="listens" xsi:type="array">
                <item name="index=create_category:responseData" xsi:type="string">setParsed</item>
                <item name="newOption" xsi:type="string">toggleOptionSelected</item>
            </item>
        </item>
    </argument>
</field>

The Cofig Code

<?php

namespace Vendor\Module\Model\Config\Source;

class CountriesTree implements \Magento\Framework\Option\ArrayInterface
{

protected $_countryCollectionFactory;

protected $_options;

protected $_childs;


public function __construct(
    \Vendor\Module\Model\ResourceModel\Country\CollectionFactory 
 $countryCollectionFactory
) {
    $this->_countryCollectionFactory = $countryCollectionFactory;
}

public function toOptionArray()
{
    if ($this->_options === null) {
        $this->_options = $this->_getOptions();
    }
    return $this->_options;
}

protected function _getOptions($itemId = 0)
{
    $childs =  $this->_getChilds();
    $options = [];

    if (isset($childs[$itemId])) {
        foreach ($childs[$itemId] as $item) {
            $data = [
                'label' => $item->getCountry_title(),
                'value' => $item->getCountry_id(),
            ];

             if (isset($childs[$item->getCountry_id()])) {
                 $data['optgroup'] = $this->_getOptions($item->getCountry_id());
             }

            $options[] = $data;
        }
    }

    return $options;
}

protected function _getChilds()
{
    if ($this->_childs === null) {
        $this->_childs =  $this->_countryCollectionFactory->create()
            ->getGroupedChilds();
    }
    return $this->_childs;
}
}

The output looks like this enter image description here

3
  • oh...but this question was asked 7 months ago :( Oct 29, 2018 at 13:48
  • The values come from the db already. I just need on the "Add screen" when I'm not editing something stored in the db to pre select default values. I don't think this solves my problem. Also, I don't need a tree-like structure. I just have a flat list of countries.
    – Marius
    Oct 29, 2018 at 14:11
  • Yes we must use default data for this, in my case i write dataprovider but in your case this in not efficient approach, in your case via xml is suitable Oct 30, 2018 at 12:11

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.