Magento – Magento 2 : Add Filter in select ui form field

dependent-fieldsdrop-downsmagento2ui-form

In ui form, I set 2 dropdown field. Now, I want to do something like that in second dropdown value set based on first dropdown selected value.

For ex : In Customer module, There are country region dropdown field. In country If you select "United States" then, in region will display "United States" country's region.

I want to do same as like in my custom dropdown with ui-select dropdown. How to do that?

I figure out that i think it's working by this below code :

<item name="filterBy" xsi:type="array">
 <item name="target" xsi:type="string">${ $.provider }:${ $.parentScope }.country</item><!-- 'country' - db table column name where country code is saved -->
 <item name="field" xsi:type="string">country_id</item><!-- country_id field name -->
</item>

But, how it works?

Any help would be highly appreciated !!

Best Answer

we are create three form fields.

    <field name="customer_id"  formElement="select" component="Vendorename_Modulename/js/components/select-customer" >
        <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="mapper" xsi:type="object">Vendorename\Modulename\Model\Mapper</item>
                <item name="sortOrder" xsi:type="number">10</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">Select Customer</label>
            <dataScope>data.customer</dataScope>
            <componentType>field</componentType>
            <listens>
                <link name="${ $.namespace }.${ $.namespace }:responseData">setParsed</link>
            </listens>
        </settings>
        <formElements>
            <select>
                <settings>
                    <options class="Vendorename\Modulename\Ui\Component\Create\Form\Customer\CustomerOptions"/>
                </settings>
            </select>
        </formElements>
    </field>
    <field name="order_id">
        <argument name="data" xsi:type="array">
            <item name="config" xsi:type="array">
                <item name="component" xsi:type="string">Vendorename_Modulename/js/components/select-order</item>
                <item name="label" xsi:type="string" translate="true">Select Order</item>
                <item name="visible" xsi:type="boolean">true</item>
                <item name="dataType" xsi:type="string">text</item>
                <item name="mapper" xsi:type="object">Vendorename\Modulename\Model\Mapper</item>
                <item name="formElement" xsi:type="string">select</item>
                <item name="source" xsi:type="string">order_id</item>
                <item name="sortOrder" xsi:type="number">20</item>
                <item name="validation" xsi:type="array">
                    <item name="required-entry" xsi:type="boolean">true</item>
                </item>
            </item>
        </argument>
        <settings>
            <dataScope>data.order_id</dataScope>
            <listens>
                <link name="${ $.namespace }.${ $.namespace }:responseData">setParsed</link>
            </listens>
        </settings>
    </field>
    <field name="order_for">
        <argument name="data" xsi:type="array">
            <item name="config" xsi:type="array">
                <item name="label" xsi:type="string">Select Item</item>
                <item name="visible" xsi:type="boolean">true</item>
                <item name="dataType" xsi:type="string">text</item>
                <item name="formElement" xsi:type="string">select</item>
                <item name="sortOrder" xsi:type="number">30</item>
                <item name="validation" xsi:type="array">
                    <item name="required-entry" xsi:type="boolean">true</item>
                </item>
            </item>
        </argument>
    </field>

Now Create an customer Option

Vendorename\Modulename\Ui\Component\Create\Form\Customer

CustomerOptions.php

<?php

namespace Vendorename\Modulename\Ui\Component\Create\Form\Customer;

use Magento\Customer\Model\ResourceModel\Customer\CollectionFactory as CustomerCollectionFactory;
use Magento\Framework\App\RequestInterface;
use Magento\Framework\Data\OptionSourceInterface;

class CustomerOptions implements OptionSourceInterface
{

    protected $customerCollectionFactory;
    protected $_orderCollectionFactory;
    protected $request;
    protected $customerTree;

    public function __construct(
        CustomerCollectionFactory $customerCollectionFactory,
        \Magento\Sales\Model\ResourceModel\Order\CollectionFactory $orderCollectionFactory,
        RequestInterface $request
    ) {
        $this->customerCollectionFactory = $customerCollectionFactory;
        $this->_orderCollectionFactory = $orderCollectionFactory;
        $this->request = $request;
    }
    public function toOptionArray()
    {
        return $this->getCustomerTree();
    }
    protected function getCustomerTree()
    {
        $customerById = [];
        if ($this->customerTree === null) {
            $collection = $this->customerCollectionFactory->create();
            if (count($collection)) {
                $collection->addNameToSelect();
                foreach ($collection as $customer) {
                    $customerId = $customer->getEntityId();
                    $Ordercollection = $this->_orderCollectionFactory->create();
                    $Ordercollection->addFieldToFilter('customer_id', $customerId);
                    if (count($Ordercollection)) {
                        if (!isset($customerById[$customerId])) {
                            $customerById[$customerId] = [
                                'value' => $customerId,
                            ];
                            $customerById[$customerId]['label'] = $customer->getName() .
                            " ( " . $customer->getEmail() . ")";
                        }
                    }
                }
                $cust_count = count($customerById);
                if ($cust_count == 0) {
                    $options[] = [
                        'label' => 'You have no Order',
                        'value' => '',
                    ];
                    return $options;
                }
                $this->customerTree = $customerById;
                return $this->customerTree;
            } else {
                $options[] = [
                    'label' => 'You have no Oreder',
                    'value' => '',
                ];
                return $options;
            }
        }
    }
}

Now we create a Mapper which provide a order Id and Order items options.

Vendorename\Modulename\Model

Mapper.php

<?php

namespace Vendorename\Modulename\Model;

class Mapper
{
    public $map;
    public $map1;
    protected $_orderCollectionFactory;
    protected $orderRepository;

    public function __construct(
        \Magento\Sales\Model\ResourceModel\Order\CollectionFactory $orderCollectionFactory,
        \Magento\Sales\Api\OrderRepositoryInterface $orderRepository
    ) {
        $this->_orderCollectionFactory = $orderCollectionFactory;
        $this->orderRepository = $orderRepository;
        $this->map = $this->makeMap();
        $this->map1 = $this->makeMapItem();
    }
    private function makeMap()
    {
        if ($this->map == null) {
            $this->map = $this->buildMap();
        }
        return $this->map;
    }
    private function makeMapItem()
    {
        if ($this->map1 == null) {
            $this->map1 = $this->buildMapItems();
        }
        return $this->map1;
    }
    private function buildMap()
    {
        $order = $this->_orderCollectionFactory->create()
            ->addAttributeToSelect('*');
        $items = [];
        $options = [];
        $result = [];
        foreach ($order->getData() as $attribute) {
            if ($attribute['customer_id'] != '') {
                $result[$attribute['customer_id']][] = [
                    'label' => $attribute['increment_id'], 'value' => $attribute['increment_id'],
                ];
            }
        }
        return $result;
    }

    private function buildMapItems()
    {
        $result = [];
        $orderCollection = $this->_orderCollectionFactory->create()
            ->addAttributeToSelect('*');
        foreach ($orderCollection as $attribute) {
            if ($attribute->getCustomerId() != '') {
                $order_id = $attribute->getIncrementId();
                $order_data = $this->orderRepository->get($order_id);
                if (!empty($order_data)) {
                    foreach ($order_data->getAllItems() as $value) {
                        $result[$order_id][] = [
                            'label' => $value->getName(), 'value' => $value->getProductId(),
                        ];
                    }
                }
            }
        }
        return $result;
    }
}

Now we add Jquery files

for customer

Vendorename/Modulename/view/adminhtml/web/js/components

select-customer.js

define([
    'Magento_Ui/js/form/element/ui-select',
    'uiRegistry',
], function (Select,uiRegistry) {
    'use strict';
    return Select.extend({
         defaults: {
            mapper: []
        },

         initialize: function (){

            var order_id = uiRegistry.get('index = order_id');
            var order_for  = uiRegistry.get('index = order_for');
            order_id.hide();
            order_for.hide();
            return this._super();
            return this.setDependentOptions(this.value());

        },

        setParsed: function (data) {
            var option = this.parseData(data);
            if (data.error) {
                return this;
            }
            this.options([]);
            this.setOption(option);
            this.set('newOption', option);
        },

        onUpdate: function (value) {
           var order_id_1 = uiRegistry.get('index = order_id');
           var order_for_1  = uiRegistry.get('index = order_for');
           order_id_1.show();
           order_for_1.show();
           this.setDependentOptions(value);
           return this._super();
        },

        setDependentOptions: function (value) {
           var options = this.mapper['map'][value];
           var field = uiRegistry.get('index = order_id');
           field.setOptions(options);
           return this;
        },

        parseData: function (data) {
            return {
                value: data.customer.entity_id,
                label: data.customer.name
            };
        }
    });
});

for order

Vendorename/Modulename/view/adminhtml/web/js/components

select-order

define([
    'underscore',
    'uiRegistry',
    'Magento_Ui/js/form/element/select',
], function (_, uiRegistry, select) {
    'use strict';
    return select.extend({
        defaults: {
            mapper: []
        },

        setParsed: function (data) {
            var option = this.parseData(data);
            if (data.error) {
                return this;
            }
            this.options([]);
            this.setOption(option);
            this.set('newOption', option);
        },

        onUpdate: function (value) {
            this.setDependentOptions(value);
            return this._super();
        },

        setDependentOptions: function (value) {
            var options = this.mapper['map1'][value];
            var field = uiRegistry.get('index = order_for');
            field.setOptions(options);
            return this;
        },

        parseData: function (data) {
            return {
                value: data.order_id.increment_id,
                label: data.order_id.get_name
            };
        }
    });
});
Related Topic