1

I am trying to group the option using optgroup for ui-select component in magento2 grid, but facing some issue. It is working fine with the [label,value] options not with optgroup.

What i am trying to achieve?

  • Need to show the dropdown with optgroup in grid filter
  • Below is the optgroup
{
                  "options": [
                    {
                      "value": "5",
                      "is_active": "1",
                      "label": "Default Category",
                      "optgroup": [
                        {
                          "value": "1",
                          "is_active": "1",
                          "label": "first sub category",
                          "optgroup": [
                            {
                              "value": "4",
                              "is_active": "1",
                              "label": "subcategory child one"
                            },
                            {
                              "value": "3",
                              "is_active": "1",
                              "label": "subcategory child two"
                            }
                          ]
                        }
                      ]
                    }
                  ],
                  "total": 10
                }
  • On search, need to call ajax and get the result

  • Below is the adminhtml ui component code

<?xml version="1.0" encoding="UTF-8"?>
<listing xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd">
    <listingToolbar name="listing_top">

    <filters name="listing_filters">
    <filterSelect
        name="store_id11"
        provider="${ $.parentName }"
        sortOrder="150"
        component="Magento_Ui/js/form/element/ui-select"
        template="Magento_MediaGalleryUi/grid/filters/elements/ui-select">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <!--<item name="entityType" xsi:type="string">cms_page</item>
                    <item name="identityColumn" xsi:type="string">page_id</item>-->
                    <item name="filterOptions" xsi:type="boolean">true</item>
                    <item name="searchOptions" xsi:type="boolean">true</item>
                    <item name="isDisplayMissingValuePlaceholder" xsi:type="boolean">true</item>
                    <item name="isDisplayEmptyPlaceholder" xsi:type="boolean">true</item>
                    <item name="isRemoveSelectedIcon" xsi:type="boolean">true</item>
                    <item name="filterPlaceholder" xsi:type="string" translate="true">Asset Title</item>
                    <item name="emptyOptionsHtml" xsi:type="string" translate="true">Start typing to find assets</item>
                    <item name="filterRateLimit" xsi:type="string" translate="true">1000</item>
                    <item name="filterRateLimitMethod" xsi:type="string" translate="true">notifyWhenChangesStop</item>
                    <item name="searchUrl" xsi:type="url" path="customwebsitelist/employee/index" />
                    <!--item name="validationUrl" xsi:type="url" path="media_gallery/asset/getSelected"/-->
                    <!--item name="levelsVisibility" xsi:type="number">1</item-->
                    <item name="multiple" xsi:type="boolean">false</item>
                    <!--<item name="formElement" xsi:type="string">select</item>
                    <item name="componentType" xsi:type="string">field</item>-->
                    <item name="listens" xsi:type="array">
                        <item name="${ $.namespace }.${ $.namespace }:responseData" xsi:type="string">setParsed</item>
                    </item>
                </item>
            </argument>
            <settings>

                <caption translate="true">– Please Select assets –</caption>
                <label translate="true">Asset1</label>
                <dataScope>store_id11</dataScope>
            </settings>
            </filterSelect>
        </filters>
    </listingToolbar>
</listing>
  • Below is the dropdown in sales order grid

enter image description here

  • Below is the issue.

enter image description here

If we select any child option it is throwing error as "Entity1 with ID: %s doesn't exist".

Please help me to fix this issue.

3
  • Have the same issue. Did you ever find a solution? Thanks Commented Aug 18, 2022 at 15:38
  • The issue is related to not properly implemented logic in core. ui-select is not designed for using tree and search together, only static tree. If I will have a time I will check about workaround for (needs to write custom ui-select component) Commented Aug 18, 2022 at 16:59
  • Yes, it is working with validationUrl. Thanks.
    – Naveen BT
    Commented Aug 23, 2022 at 9:58

2 Answers 2

2
+50

1. Create Custom UI Select Component

app/code/Acme/StackExchange/view/base/web/js/grid/filters/elements/ui-select.js

define([
    'Magento_Ui/js/grid/filters/elements/ui-select',
    'underscore'
], function (Select, _) {
    'use strict';

    return Select.extend({
        getSelected: function () {
            if (!this.searchOptions) {
                return this._super();
            }

            return this.lookupSelectedOptions(this.cacheOptions.plain, this.value());
        },
        /**
         * @param {*[]} source
         * @param {*[]|String} selected
         * @param {*[]|null} result
         * @param {String|null} separator
         * @returns {*[]}
         */
        lookupSelectedOptions: function (source, selected, result, separator) {
            let i = 0, length;
            separator = separator || this.separator;
            result    = result || [];
            source = _.compact(source);
            length = source.length;

            for (i; i < length; i++) {
                if (_.isArray(selected) ? _.contains(selected, source[i].value) : selected == source[i].value) {
                    result.push(source[i]);
                }

                if (source[i].hasOwnProperty(separator)) {
                    this.lookupSelectedOptions.call(this, source[i][separator], selected, result);
                }
            }

            return result;
        }
    });
});

2. Use Custom UI Component

<filterSelect component="Acme_StackExchange/js/grid/filters/elements/ui-select"

enter image description here

P.S. Don't forget to implement <item name="validationUrl" xsi:type="url" path="acme/select/validation"/> for lookup dynamic options labels on load

1
  • I went with the approach I mentioned above, but this looks like it could also work. Thanks Commented Aug 19, 2022 at 21:58
0

I found a solution for this. Basically you need to provide the already chosen value as a select option. Here's an example of what I mean

<field name="product_1" component="Magento_Ui/js/form/element/ui-select" formElement="select">
        <argument name="data" xsi:type="array">
            <item name="config" xsi:type="array">
                <item name="filterOptions" xsi:type="boolean">true</item>
                <item name="multiple" xsi:type="boolean">false</item>
                <item name="showCheckbox" xsi:type="boolean">true</item>
                <item name="disableLabel" xsi:type="boolean">true</item>
                <item name="levelsVisibility" xsi:type="number">1</item>
                <item name="isRemoveSelectedIcon" xsi:type="boolean">true</item>
                <item name="searchOptions" xsi:type="boolean">true</item>
                <item name="searchUrl" xsi:type="url" path="catalog/product/search"/>
                <item name="filterPlaceholder" xsi:type="string" translate="true">Product Name or SKU</item>
                <item name="emptyOptionsHtml" xsi:type="string" translate="true">Start typing to find products</item>
                <item name="source" xsi:type="string">look</item>
                <item name="filterRateLimit" xsi:type="number">1000</item>
                <item name="filterRateLimitMethod" xsi:type="string" translate="true">notifyWhenChangesStop</item>
            </item>
        </argument>
        <settings>
            <required>true</required>
            <validation>
                <rule name="required-entry" xsi:type="boolean">true</rule>
            </validation>
            <elementTmpl>ui/grid/filters/elements/ui-select</elementTmpl>
            <label translate="true">Product 1</label>
            <dataScope>product_1</dataScope>
            <componentType>field</componentType>
            <listens>
                <link name="${ $.namespace }.${ $.namespace }:responseData">setParsed</link>
            </listens>
        </settings>
        <formElements>
            <select>
                <settings>
                    <options class="Vendor\Module\Ui\Component\Look\Column\Product1\Options" />
                </settings>
            </select>
        </formElements>
    </field>

Where what I added to fix the issue is this section

<formElements>
        <select>
            <settings>
                <options class="Vendor\Module\Ui\Component\Look\Column\Product1\Options" />
            </settings>
        </select>
    </formElements>

Where this options class is making a query to my custom table and getting the product ID and the product name and creating a single option with those as value => label and returning it. This works perfectly; now when the form loads the product chooser will show the already selected option the same way it does when the option is first selected

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.