0

Is there a way to make some listing select in filter to depend on some other select? I have seen this done on frontend checkout but that's a form not a list.

The idea is to make two columns searchable by select values but second select values are filtered by first option's value.

I tried something like this (similar to checkout implementation) but it does not work.

<column name="customer_id">
    <argument name="data" xsi:type="array">
        <item name="options" xsi:type="object">Module\Module\Model\Config\Source\Customers</item>
        <item name="config" xsi:type="array">
            <item name="filter" xsi:type="string">select</item>
            <item name="label" xsi:type="string" translate="true">Customer</item>
            <item name="component" xsi:type="string">Magento_Ui/js/grid/columns/select</item>
            <item name="dataType" xsi:type="string">select</item>
            <item name="dataScope" xsi:type="string">customer</item>
            <item name="sortOrder" xsi:type="number">75</item>
            <item name="sortable" xsi:type="boolean">false</item>
        </item>
    </argument>
</column>

<column name="address_id">
    <argument name="data" xsi:type="array">
        <item name="options" xsi:type="object">Module\Module\Model\Config\Source\Address</item>
        <item name="config" xsi:type="array">
            <item name="filter" xsi:type="string">select</item>
            <item name="label" xsi:type="string" translate="true">Address</item>
            <item name="component" xsi:type="string">Magento_Ui/js/grid/columns/select</item>
            <item name="dataType" xsi:type="string">select</item>
            <item name="dataScope" xsi:type="string">address_id</item>
            <item name="sortOrder" xsi:type="number">75</item>
            <item name="sortable" xsi:type="boolean">false</item>
            <item name="filterBy" xsi:type="array">
                <item name="target" xsi:type="string">${ $.provider }:${ $.parentScope }.customer_id</item>
                <item name="field" xsi:type="string">customer_id</item>
            </item>
        </item>
    </argument>
</column>
2
  • Did you solved this issue? Commented Nov 8, 2019 at 6:09
  • @RohanHapani see my answer below. Maybe there is some error because I edited my code before I copied (I had to rename/delete some stuff).
    – Artis Z
    Commented Nov 8, 2019 at 9:01

1 Answer 1

0

Feels like hacky solution but it works:

Ui component listing:

<filters name="listing_filters">
        <argument name="data" xsi:type="array">
            <item name="config" xsi:type="array">
                <item name="columnsProvider" xsi:type="string">grid_listing.grid_listing.grids_columns</item>
                <item name="storageConfig" xsi:type="array">
                    <item name="provider" xsi:type="string">grid_listing.grid_listing.listing_top.bookmarks</item>
                    <item name="namespace" xsi:type="string">current.filters</item>
                </item>
                <item name="templates" xsi:type="array">
                    <item name="filters" xsi:type="array">
                        <item name="select" xsi:type="array">
                            <item name="component" xsi:type="string">Magento_Ui/js/form/element/select-custom</item>
                            <item name="template" xsi:type="string">ui/grid/filters/elements/select-custom</item>
                        </item>
                    </item>
                </item>
                <item name="childDefaults" xsi:type="array">
                    <item name="provider" xsi:type="string">grid_listing.grid_listing.listing_top.listing_filters</item>
                    <item name="imports" xsi:type="array">
                        <item name="visible" xsi:type="string">grid_listing.grid_listing.grid_columns.${ $.index }:visible</item>
                    </item>
                </item>
            </item>
            <item name="observers" xsi:type="array">
                <item name="column" xsi:type="string">column</item>
            </item>
        </argument>
    <filterSelect name="address_id" provider="${ $.parentName }">
        <settings>
            <options class="Vendor\Module\Model\Config\Source\Address"/>
            <label translate="true">Address</label>
            <dataScope>address_id</dataScope>
            <imports>
                <link name="visible">ns = ${ $.ns }, componentType = column, index = ${ $.index }:visible</link>
            </imports>
        </settings>
    </filterSelect>
    <filterSelect name="customer_id" provider="${ $.parentName }">
        <settings>
            <options class="Vendor\Module\Model\Config\Source\Customers"/>
            <label translate="true">Customer</label>
            <dataScope>customer_id</dataScope>
            <imports>
                <link name="visible">ns = ${ $.ns }, componentType = column, index = ${ $.index }:visible</link>
            </imports>
        </settings>
    </filterSelect>
</filters>

js:

define([
    'Magento_Ui/js/form/element/select',
    'jquery',
    'uiRegistry',
    'mage/url'
], function (Select, $, uiRegistry, url) {
    'use strict';

    function parseOptions(nodes, captionValue) {
        var caption,
            value;

        nodes = _.map(nodes, function (node) {
            value = node.value;

            if (value === null || value === captionValue) {
                if (_.isUndefined(caption)) {
                    caption = node.label;
                }
            } else {
                return node;
            }
        });

        return {
            options: _.compact(nodes),
            caption: _.isString(caption) ? caption : false
        };
    }

    function findFirst(data) {
        var value;

        data.some(function (node) {
            value = node.value;

            if (Array.isArray(value)) {
                value = findFirst(value);
            }

            return !_.isUndefined(value);
        });

        return value;
    }

    function indexOptions(data, result) {
        var value;

        result = result || {};

        data.forEach(function (item) {
            value = item.value;

            if (Array.isArray(value)) {
                indexOptions(value, result);
            } else {
                result[value] = item;
            }
        });

        return result;
    }

    return Select.extend({

        initialize: function () {
            self = this;
            this._super();

            if (this.customEntry) {
                registry.get(this.name, this.initInput.bind(this));
            }

            if (this.filterBy) {
                this.initFilter();
            }

            // filter and update address select

            if (this.inputName == 'address_id' && this.source.filters.customer_id !== undefined) {

                this.filterBy = {
                    field: 'customer_id',
                    target: 'customer_id'
                }

                this.customerFilter(this.source.filters.customer_id, 'customer_id');
            }

            return this;
        },

        customerFilter: function (value, field) {
            var source = this.initialOptions,
                result;

            result = _.filter(source, function (item) {
                return item[field] === value || item.value === '';
            });

            this.setOptions(result);
        },

        onUpdate: function () {
            var self = this;

            this.bubble('update', this.hasChanged());

            this.validate();

            // filter and update address select

            if (this.inputName == 'customer_id') {

                var address = uiRegistry.get(this.parentName + '.' + 'address_id'),
                    options = address.indexedOptions,
                    source = address.initialOptions,
                    result;

                result = _.filter(source, function (item) {
                    return item[self.inputName] === self.value();
                });

                address.setOptions(result);
            }
        }
    });
});

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.