Dependent fields in ui-component forms in Magento 2 without Javascript
This article is going to show you how to define field dependencies between ui-component form fields. There are several articles out there explaining how to do it using Javascript, however, there is nothing really that explains how to do it without Javascript, by just using XML. Most of the cases are usually simple and using Javascript for handling field dependencies would be more than what’s necessary. For such cases, you can use the solution discussed in this article.
This method is going to use something called as the switcherConfig
that is
available in Magento. switcherConfig
allows you to define rules for handling actions on field value updates. It doesn’t necessarily have to be show/hide, but you can use different callbacks and pass arguments to the callbacks, thus
allowing you to handle basic to moderate level of actions on fields by just using the XML schema.
I will keep things simple in this tutorial, and handle only 3 fields. The first field will be the field on which the other 2 fields will depend.
Following will be the fields in our form:
- Color type - will be a dropdown field that will have 2 options. Each option selection would trigger the visibility changes of the other 2 fields.
- List - will be a dropdown field list of colors
- Hex code - will be a text field wherein you can enter the hex code for the color.
Following is roughly how our form schema looks:
<?xml version="1.0" ?>
<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">hs_xml_dependentfield_model_form.model_form_data_source</item>
</item>
...
</argument>
<settings>
...
<namespace>hs_xml_dependentfield_model_form</namespace>
...
</settings>
...
<fieldset name="general">
...
<field name="color_type" formElement="select" sortOrder="40">
...
<settings>
<dataType>string</dataType>
...
</settings>
<formElements>
<select>
<settings>
<options>
<option name="0" xsi:type="array">
<item name="value" xsi:type="number">list</item>
<item name="label" xsi:type="string" translate="true">List</item>
</option>
<option name="1" xsi:type="array">
<item name="value" xsi:type="number">hex_code</item>
<item name="label" xsi:type="string" translate="true">Hex code</item>
</option>
</options>
</settings>
</select>
</formElements>
</field>
<field formElement="select" name="list" sortOrder="50">
...
</field>
<field formElement="input" name="html" sortOrder="80">
...
</field>
</fieldset>
</form>
Note: This tutorial assumes that you’ve got the form to show up correctly on your page and will only handle trigger actions on field value updates.
Now that our form is ready and working, let us add the switcherConfig
so that certain callbacks are called on value updates. We will add our switcherConfig
to the color_type
field because we
want to track the value updates on this field and take necessary actions when the current value of the field matches a certain value.
Note: We will consider a string
valued select/dropdown field instead of a boolean because handling boolean is much easier and doesn’t need switcherConfig
.
Adding switcherConfig
to the
field settings
Start by adding the switcherConfig
a child of the <settings>...</settings>
element of your field. Following is the
switcherConfig
that adds a rule the triggers the defined actions when the value of the color_type
dropdown matches list
. On a positive match, 2 actions are trigger.
- Show the field
list
with a list of colors. - Hide the field
hex_code
that allows you to enter the hexadecimal code of the color.
You can add a similar rule to match the value hex_code
and do the opposite actions to show the hex_code
field and hide the
list
field. I am not going to add that XML here.
Important: If you notice the below piece of XML, you see that the tag <rule />
,
<action />
and <param />
have their name attribute set to an integer. This is very important because Magento considers each of these as items of an array, and loops using forEach
method on array.
Adding a string name to any of these would trigger an error, because forEach
only works on arrays and not objects.
<switcherConfig>
<rules>
<rule name="0">
<value>list</value><!-- Actions defined will be trigger when the current selected field value matches the value defined here-->
<actions>
<action name="0">
<target>hs_xml_dependentfield_model_form.hs_xml_dependentfield_model_form.general.list</target>
<callback>visible</callback>
<params>
<param name="0" xsi:type="boolean">true</param>
</params>
</action>
<action name="1">
<target>hs_xml_dependentfield_model_form.hs_xml_dependentfield_model_form.general.hex_code</target>
<callback>visible</callback>
<params>
<param name="0" xsi:type="boolean">true</param>
</params>
</action>
</actions>
</rule>
...
</rules>
<enabled>true</enabled>
</switcherConfig>
<target>
- define the registry key where the dependent field component is saved in the registry.
<callback>
- a callable method available in the component. If you use a custom component, you can call that method.
<param>
- value to be passed to the callback method. I am passing a boolean
value, you can pass anything to your callback and handle the logic.
If
you would like to dig into the code to see how things work, go to switcher.js and check applyRule
and
applyAction
methods, and uiRegistry.
Hope this helps. In another tutorial, I will show you how to handle dependencies in an even more simpler manner for boolean
or Yes/No
dropdown options.