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.

asked Mar 29, 2018 at 6:57
11
  • did you try with the id of the options? Commented 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 Commented Mar 29, 2018 at 8:50
  • <items name="default" xsi:type="array"> </items> Commented Mar 29, 2018 at 9:57
  • @IdhamChoudry I already tried that. It says so in the question. Commented 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' => ...] Commented 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

answered Oct 29, 2018 at 13:43
3
  • oh...but this question was asked 7 months ago :( Commented 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. Commented 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 Commented Oct 30, 2018 at 12:11

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.