1

So I'm trying to create dependent field, that would appear if the respective drop-down value will be chosen. My widget.xml looks like this:

<widgets xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Widget:etc/widget.xsd">
    <widget id="DemoWidget" class="Demo\DemoWidget\Block\Widget\Demo" placeholder_image="Demo_DemoWidget::logo.png">
        <label translate="true">Demo Widget</label>
        <description translate="true">Demo widget</description>
        <parameters>
            <parameter name="is_enabled" xsi:type="select" visible="true" sort_order="10">
                <label translate="true">Is Enabled?</label>
                <options>
                    <option name="1" value="1">
                        <label>Yes</label>
                    </option>
                    <option name="0" value="0">
                        <label>No</label>
                    </option>
                </options>
            </parameter>
            <parameter name="link_url" xsi:type="block" visible="true" sort_order="20">
                <label translate="true">Link URL</label>
                <block class="Demo\DemoWidget\Block\Adminhtml\Widget\UrlInput"></block>
                <depends>
                    <parameter name="is_enabled" value="1"></parameter>
                </depends>
            </parameter>
        </parameters>
    </widget>
</widgets>

Of course, it doesn't work - I see both drop-down and block input, but changing the drop-down doesn't work at all. I was trying to find a solution, and this one seemed to be very promising. However, after I implemented it, the admin panel shows me this error: Element 'depends': This element is not expected.

It wasn't the case before I followed the instruction from the above mentioned solution, so I assume it worked in a certain way. However, as far as I know, <depends> should be possible to use in widget.xml, so I'm very lost. Does anyone have any solution/ideas on how to fix that?

My requirejs-config.js, which is located ad DemoWidget/view/adminhtml/web(I also tried to move it to adminhtml folder, used a couple of versions of path to form, didn;t work):

var config = {
    map: {
        "*": {
            "mage/adminhtml/form": "DemoWidget/view/adminhtml/web/js/form"
        }
    }
};

And this is the trackChange() I used instead of original one in DemoWidget/view/adminhtml/web/js/form.js file:

trackChange : function(e, idTo, valuesFrom)
         {
             // define whether the target should show up
             var shouldShowUp = true;
             for (var idFrom in valuesFrom) {
                 var from = $(idFrom);
                 if (from) {
                     var values = valuesFrom[idFrom]['values'];
                     var isInArray = values.indexOf(from.value) != -1;
                     var isNegative = valuesFrom[idFrom]['negative'];
                     if (!from || isInArray && isNegative || !isInArray && !isNegative) {
                         shouldShowUp = false;
                     }
                 }
             }
     
             // toggle target row
             var headElement = $(idTo + '-head'),
                 isInheritCheckboxChecked = $(idTo + '_inherit') && $(idTo + '_inherit').checked,
                 target = $(idTo);
     
             // Custom code to account for the chooser style parameters.
             if (target === null && headElement === null && idTo.substring(0, 16) === 'options_fieldset') {
                 headElement = jQuery('.field-' + idTo).add('.field-chooser' + idTo);
             }
     
             // Target won't always exist (for example, if field type is "label")
             if (target) {
                 var inputs = target.up(this._config.levels_up).select('input', 'select', 'td'),
                     isAnInputOrSelect = ['input', 'select'].indexOf(target.tagName.toLowerCase()) != -1;
             } else {
                 var inputs = false,
                     isAnInputOrSelect = false;
             }
             if (shouldShowUp) {
                 var currentConfig = this._config;
                 if (inputs) {
                     inputs.each(function (item) {
                         // don't touch hidden inputs (and Use Default inputs too), bc they may have custom logic
                         if ((!item.type || item.type != 'hidden') && !($(item.id+'_inherit') && $(item.id+'_inherit').checked)
                             && !(currentConfig.can_edit_price != undefined && !currentConfig.can_edit_price)) {
                             item.disabled = false;
                             jQuery(item).removeClass('ignore-validate');
                         }
                     });
                 }
                 if (headElement) {
                     headElement.show();
                     if (target && headElement.hasClassName('open')) {
                         target.show();
                     } else if (target) {
                         target.hide();
                     }
                 } else {
                     if (target) {
                         target.show();
                     }
                     if (isAnInputOrSelect && !isInheritCheckboxChecked) {
                         if (target) {
                             target.disabled = false;
                         }
                         jQuery('#' + idTo).removeClass('ignore-validate');
                     }
                 }
             } else {
                 if (inputs) {
                     inputs.each(function (item){
                         // don't touch hidden inputs (and Use Default inputs too), bc they may have custom logic
                         if ((!item.type || item.type != 'hidden') && !($(item.id+'_inherit') && $(item.id+'_inherit').checked)) {
                             item.disabled = true;
                             jQuery(item).addClass('ignore-validate');
                         }
                     });
                 }
                 if (headElement) {
                     headElement.hide();
                 }
                 if (target) {
                     target.hide();
                 }
                 if (isAnInputOrSelect && !isInheritCheckboxChecked) {
                     if (target) {
                         target.disabled = true;
                     }
                     jQuery('#' + idTo).addClass('ignore-validate');
                 }
     
             }
             var rowElement = $('row_' + idTo);
             if (rowElement == undefined && target) {
                 rowElement = target.up(this._config.levels_up);
             }
             if (rowElement) {
                 if (shouldShowUp) {
                     rowElement.show();
                 } else {
                     rowElement.hide();
                 }
             }
         }

2 Answers 2

1

I checked it on Magento 2.4.3 and additionally I had to move depends element above the block element.

From vendor\magento\module-widget\etc\widget.xsd there is defined sequence (around lines 63-79)

 <xs:complexType name="parameterType" abstract="true">
    <xs:annotation>
        <xs:documentation>
            Abstract type which is parent of all parameters. Contains attributes
            and elements common across all parameter types.
        </xs:documentation>
    </xs:annotation>
    <xs:sequence>
        <xs:element name="label" type="translatableType" minOccurs="0" maxOccurs="1" />
        <xs:element name="description" type="translatableType" minOccurs="0" maxOccurs="1" />
        <xs:element name="depends" type="dependsType" minOccurs="0" maxOccurs="1" />
    </xs:sequence>
    <xs:attribute name="name" type="xs:NMTOKEN" use="required" />
    <xs:attribute name="visible" type="xs:boolean" />
    <xs:attribute name="sort_order" type="xs:int" />
    <xs:attribute name="required" type="xs:string" />
</xs:complexType>

That is why the admin shows the error:

Element 'depends': This element is not expected.

Further in schema file there is block element, defined by this fragment (around 91-102 lines) :

<xs:complexType name="block">
    <xs:annotation>
        <xs:documentation>Parameter type which supplies a renderer.</xs:documentation>
    </xs:annotation>
    <xs:complexContent>
        <xs:extension base="parameterType">
            <xs:sequence>
                <xs:element name="block" type="blockType" />
            </xs:sequence>
        </xs:extension>
    </xs:complexContent>
</xs:complexType>

So we need to arrange the elements in a specific order. Element depends has to be before the block element.

Here is my solution without using source_model attribute (check Rahul Barot's example). I added attribute selected for option element:

<widgets xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Widget:etc/widget.xsd">
<widget id="DemoWidget" class="Demo\DemoWidget\Block\Widget\Demo" placeholder_image="Demo_DemoWidget::logo.png">
    <label translate="true">Demo Widget</label>
    <description translate="true">Demo widget</description>
    <parameters>
        <parameter name="is_enabled" xsi:type="select" visible="true" sort_order="10">
            <label translate="true">Is Enabled?</label>
            <options>
                <option name="1" value="1">
                    <label>Yes</label>
                </option>
                <option name="0" value="0" selected="true">
                    <label>No</label>
                </option>
            </options>
        </parameter>
        <parameter name="cms_chooser" xsi:type="block" visible="true" sort_order="20">
            <label translate="true">Cms Block</label>
            <depends>
                <parameter name="is_enabled" value="1"/>
            </depends>
            <block class="Magento\Cms\Block\Adminhtml\Block\Widget\Chooser"/>
        </parameter>
    </parameters>
</widget>

That's all. No need for additional js code. In this example, I used the existing block in Magento.

2
  • thanks for the explanation, I've updated my answer accordingly. Jul 1, 2022 at 5:22
  • Thank you very much! That was really detailed and helpful - I did as instructed, and it worked immediately :) Jul 1, 2022 at 8:22
0

Try with the below widget.xml and let me know if it works for you. I've changed the select dropdown code to use the source model.

<widgets xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Widget:etc/widget.xsd">
<widget id="DemoWidget" class="Demo\DemoWidget\Block\Widget\Demo" placeholder_image="Demo_DemoWidget::logo.png">
        <label translate="true">Demo Widget</label>
        <description translate="true">Demo widget</description>
        <parameters>
            <parameter name="is_enabled" xsi:type="select" visible="true" sort_order="10"
                source_model="Magento\Config\Model\Config\Source\Yesno">
                <label translate="true">Is Enabled?</label>
            </parameter>
            <parameter name="link_url" xsi:type="block" visible="true" sort_order="20">
                <label translate="true">Link URL</label>
                <depends>
                    <parameter name="is_enabled" value="1"></parameter>
                </depends>
                <block class="Demo\DemoWidget\Block\Adminhtml\Widget\UrlInput"></block>
            </parameter>
        </parameters>
    </widget>
</widgets>
1
  • Thank you very much, I appreciate your effort to help! Unfortunately, I can't upvote your answer since I don't have 15 reputation so far, but I will come back to it once I'll have it! Jul 1, 2022 at 8:24

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.