3

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 !!

7
2

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
            };
        }
    });
});
0
1

You can set dependency using following way, here I can used two separate tables as an example, Authors & Books and created models and resource models for both and add foreign key in Books table with author_id.

/app/code/Vendor/Uidemo/view/adminhtml/ui_component/uidemo_form.xml

<?xml version="1.0" encoding="UTF-8"?>
<!--
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */
-->
<form xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd">
    <argument name="data" xsi:type="array">
        <item name="js_config" xsi:type="array">
            <item name="provider" xsi:type="string">uidemo_form.uidemo_form_data_source</item>
            <item name="deps" xsi:type="string">uidemo_form.uidemo_form_data_source</item>
        </item>
        <item name="config" xsi:type="array">
            <item name="dataScope" xsi:type="string">data</item>
            <item name="namespace" xsi:type="string">uidemo_form</item>
        </item>
        <item name="spinner" xsi:type="string">uidemo_information</item>
        <item name="template" xsi:type="string">templates/form/collapsible</item>
    </argument>
    <dataSource name="uidemo_form_data_source">
        <argument name="dataProvider" xsi:type="configurableObject">
            <argument name="class" xsi:type="string">Vendor\Uidemo\Ui\Component\Form\Uidemo\DataProvider</argument>
            <argument name="name" xsi:type="string">uidemo_form_data_source</argument>
            <argument name="primaryFieldName" xsi:type="string">author_id</argument>
            <argument name="requestFieldName" xsi:type="string">author_id</argument>
            <argument name="data" xsi:type="array">
              <item name="config" xsi:type="array">
                 <item name="submit_url" xsi:type="url" path="*/*/save"/>
              </item>
            </argument>
        </argument>
        <argument name="data" xsi:type="array">
            <item name="js_config" xsi:type="array">
                <item name="component" xsi:type="string">Magento_Ui/js/form/provider</item>
            </item>
        </argument>
    </dataSource>
    <fieldset name="uidemo_information">
        <argument name="data" xsi:type="array">
            <item name="config" xsi:type="array">
                <item name="collapsible" xsi:type="boolean">false</item>
                <item name="label" xsi:type="string" translate="true">Books Details</item>
                <item name="sortOrder" xsi:type="number">20</item>
            </item>
        </argument>
        <field name="author_id">
            <argument name="data" xsi:type="array">
                <item name="options" xsi:type="object">Vendor\Uidemo\Model\Config\Source\Author</item>
                <item name="config" xsi:type="array">
                    <item name="dataType" xsi:type="string">text</item>
                    <item name="label" xsi:type="string" translate="true">Author</item>
                    <item name="formElement" xsi:type="string">select</item>
                    <item name="source" xsi:type="string">author</item>
                </item>
            </argument>
        </field>
        <field name="book_name">
            <argument name="data" xsi:type="array">
                <item name="options" xsi:type="object">Vendor\Uidemo\Model\Config\Source\Books</item>
                <item name="config" xsi:type="array">
                    <item name="dataType" xsi:type="string">text</item>
                    <item name="label" xsi:type="string" translate="true">Book</item>
                    <item name="formElement" xsi:type="string">select</item>
                    <item name="source" xsi:type="string">author</item>
                    <item name="customEntry" xsi:type="string">name</item>
                    <item name="filterBy" xsi:type="array">
                        <item name="target" xsi:type="string">${ $.provider }:${ $.parentScope }.author_id</item>
                        <item name="field" xsi:type="string">author_id</item>
                    </item>
                </item>
            </argument>
        </field>
    </fieldset>
</form>

/app/code/Vendor/Uidemo/Model/Config/Source/Author.php

<?php
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */

namespace Vendor\Uidemo\Model\Config\Source;

use Magento\Framework\Option\ArrayInterface;

class Author implements ArrayInterface
{
    /**
     * @var \Vendor\Uidemo\Model\ResourceModel\Uidemo\Collection
     */
    protected $authorCollection;

    /**
     * [__construct description]
     * @param \Vendor\Uidemo\Model\ResourceModel\Uidemo\Collection $authorCollection [description]
     */
    public function __construct(
        \Vendor\Uidemo\Model\ResourceModel\Uidemo\Collection $authorCollection
    ) {
        $this->authorCollection = $authorCollection;
    }

    public function toOptionArray()
    {
        $collection = $this->authorCollection->getData();
        $options = [];

        foreach ($collection as $key => $value) {
            $options[] = ['value' => $value['author_id'], 'label' => $value['name']];
        }

        return $options;
    }
}

/app/code/Vendor/Uidemo/Model/Config/Source/Books.php

<?php
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */

namespace Vendor\Uidemo\Model\Config\Source;

use Magento\Framework\Option\ArrayInterface;

class Books implements ArrayInterface
{
    /**
     * @var \Vendor\Uidemo\Model\ResourceModel\Books\Collection
     */
    protected $booksCollection;

    /**
     * [__construct description]
     * @param \Vendor\Uidemo\Model\ResourceModel\Books\Collection $booksCollection [description]
     */
    public function __construct(
        \Vendor\Uidemo\Model\ResourceModel\Books\Collection $booksCollection
    ) {
        $this->booksCollection = $booksCollection;
    }

    public function toOptionArray()
    {
        $options = [];
        $propertyMap = [
            'value' => 'book_id',
            'title' => 'name',
            'author_id' => 'author_id',
        ];
        $coll = $this->booksCollection;
        foreach ($coll as $item) {
            $option = [];
            foreach ($propertyMap as $code => $field) {
                $option[$code] = $item->getData($field);
            }
            $option['label'] = $item->getName();
            $options[] = $option;
        }
        return $options;
    }
}

Output

enter image description here enter image description here

I hope it will helpful for you.

1

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.