Magento2 – Dependent Select Fields Filtering

dependencymagento2

I can use the country and state fields in admin form by just pasting the form xml explained here ui_component form state/region field update after country select (M 2.1)
Now My question is that I am making a custom module Which have cities and region and I want regions to be filtered on base of selected cities. I make the form and also listed all the data in city and region using models Which is working fine.
Below is my code for app/code/Vendor/Storemap/view/adminhtml/ui_component/vendor_branch_form.xml

<?xml version="1.0" encoding="UTF-8"?>
<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">Vendor_branch_form.storemap_branch_form_data_source</item>
            <item name="deps" xsi:type="string">Vendor_branch_form.storemap_branch_form_data_source</item>
        </item>
        <item name="label" xsi:type="string" translate="true">General</item>
        <item name="layout" xsi:type="array">
            <item name="type" xsi:type="string">tabs</item>
            <item name="navContainerName" xsi:type="string">left</item>
        </item>
        <item name="buttons" xsi:type="array">
            <item name="save" xsi:type="array">
                <item name="name" xsi:type="string">save</item>
                <item name="label" xsi:type="string" translate="true">Save</item>
                <item name="class" xsi:type="string">primary</item>
                <item name="url" xsi:type="string">*/*/save</item>
            </item>
        </item>
    </argument>
    <dataSource name="storemap_branch_form_data_source">
        <argument name="dataProvider" xsi:type="configurableObject">
            <argument name="class" xsi:type="string">Vendor\Storemap\Ui\DataProvider</argument>
            <argument name="name" xsi:type="string">storemap_branch_form_data_source</argument>
            <argument name="primaryFieldName" xsi:type="string">id_store</argument>
            <argument name="requestFieldName" xsi:type="string">id_store</argument>
            <argument name="collectionFactory" xsi:type="object">Vendor\Storemap\Model\ResourceModel\Branch\CollectionFactory</argument>
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="submit_url" xsi:type="url" path="storemap/branch/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="general">
        <argument name="data" xsi:type="array">
            <item name="config" xsi:type="array">
                <item name="label" xsi:type="string" translate="true">General</item>
            </item>
        </argument>
        <field name="store_number">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="label" xsi:type="string" translate="true">Store Number</item>
                    <item name="dataType" xsi:type="string">text</item>
                    <item name="formElement" xsi:type="string">input</item>
                    <item name="validation" xsi:type="array">
                        <item name="required-entry" xsi:type="boolean">true</item>
                    </item>
                </item>
            </argument>
        </field>
        <field name="id_city">
            <argument name="data" xsi:type="array">
                <item name="options" xsi:type="object">Vendor\Storemap\Model\System\City</item>
                <item name="config" xsi:type="array">
                    <item name="label" xsi:type="string" translate="true">City</item>
                    <item name="dataType" xsi:type="string">text</item>
                    <item name="formElement" xsi:type="string">select</item>
                    <item name="source" xsi:type="string">general</item>
                    <item name="dataScope" xsi:type="string">id_city</item>
                    <!--<item name="component" xsi:type="string">Vendor_Storemap/js/city</item>-->
                    <item name="validation" xsi:type="array">
                        <item name="required-entry" xsi:type="boolean">true</item>
                    </item>
                    <!--<item name="imports" xsi:type="array">-->
                        <!--<item name="default" xsi:type="string">${ $.provider }:data.customer.website_id</item>-->
                    <!--</item>-->
                </item>
            </argument>
        </field>

        <field name="id_region">
            <argument name="data" xsi:type="array">
                <item name="options" xsi:type="object">Vendor\Storemap\Model\ResourceModel\Region\Collection</item>
                <item name="config" xsi:type="array">
                    <item name="dataType" xsi:type="string">text</item>
                    <item name="label" xsi:type="string" translate="true">Region</item>
                    <item name="formElement" xsi:type="string">select</item>
                    <item name="source" xsi:type="string">general</item>
                    <item name="sortOrder" xsi:type="number">20</item>
                    <item name="dataScope" xsi:type="string">id_region</item>
                    <!--<item name="customEntry" xsi:type="string">region</item>-->
                    <item name="validation" xsi:type="array">
                        <item name="required-entry" xsi:type="boolean">true</item>
                    </item>
                    <item name="filterBy" xsi:type="array">
                        <item name="target" xsi:type="string">${ $.provider }:${ $.parentScope }.id_city</item><!-- 'country' - db table column name where country code is saved -->
                        <item name="field" xsi:type="string">id_city</item><!-- country_id field name -->
                    </item>
                </item>
            </argument>
        </field>

        <field name="store_mail">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="label" xsi:type="string" translate="true">Store mail</item>
                    <item name="dataType" xsi:type="string">text</item>
                    <item name="formElement" xsi:type="string">input</item>
                    <item name="validation" xsi:type="array">
                        <item name="required-entry" xsi:type="boolean">false</item>
                    </item>
                </item>
            </argument>
        </field>
        <field name="lat_lan">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="label" xsi:type="string" translate="true">lat_lan</item>
                    <item name="dataType" xsi:type="string">text</item>
                    <item name="formElement" xsi:type="string">input</item>
                    <item name="validation" xsi:type="array">
                        <item name="required-entry" xsi:type="boolean">false</item>
                    </item>
                </item>
            </argument>
        </field>

        <field name="active">
            <argument name="data" xsi:type="array">
                <item name="options" xsi:type="array">
                    <item name="0" xsi:type="array">
                        <item name="value" xsi:type="number">0</item>
                        <item name="label" xsi:type="string" translate="true">In-Acive</item>
                    </item>
                    <item name="1" xsi:type="array">
                        <item name="value" xsi:type="number">1</item>
                        <item name="label" xsi:type="string" translate="true">Active</item>
                    </item>
                </item>
                <item name="config" xsi:type="array">
                    <item name="label" xsi:type="string" translate="true">Status</item>
                    <item name="visible" xsi:type="boolean">true</item>
                    <item name="dataType" xsi:type="string">number</item>
                    <item name="formElement" xsi:type="string">select</item>
                    <item name="dataScope" xsi:type="string">active</item>
                    <item name="sortOrder" xsi:type="number">60</item>
                </item>
            </argument>
        </field>
    </fieldset>
</form>

Best Answer

After inspecting the default Country and region select I found the solution. The solution in my case was that I was not returning id_city in region collection. As in the above xml I mentioned

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

So it will expect id_country in the regions as well. Below is my code for RegionCollection file located at Vendor\Storemap\Model\ResourceModel\Region\Collection:

namespace Vendor\Storemap\Model\System;

use Magento\Framework\Data\OptionSourceInterface;
use Vendor\Storemap\Model\ResourceModel\Region\Collection;
use Vendor\Storemap\Model\ResourceModel\Region\CollectionFactory;

class Region implements OptionSourceInterface
{
    private $collectionFactory;

    public function __construct(CollectionFactory $collectionFactory)
    {
        $this->collectionFactory = $collectionFactory;
    }

    /**
     * Return array of options as value-label pairs
     *
     * @return array Format: array(array('value' => '<value>', 'label' => '<label>'), ...)
     */
    public function toOptionArray()
    {
        $options = [];
        $cities = $this->collectionFactory->create()->getItems();
        foreach ($cities as $key=>$value)
        {
            $options[] = ['label' => $value['region_en'], 'value' => $value['id_region'], 'id_city' => $value['id_city']];
        }
        return $options;
    }
}
Related Topic