Show/Hide fields dropdown inside a multifield AEM 6.5

Goal

Create a component that uses a dropdown that shows/hides fields inside a multifield.

Procedure

Let’s create our dialog as follows:

<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:granite="http://www.adobe.com/jcr/granite/1.0"
          xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:nt="http://www.jcp.org/jcr/nt/1.0"
          jcr:primaryType="nt:unstructured"
          jcr:title="Component Configuration"
          extraClientlibs="[lab2020.base.showhide-multifield]"
          sling:resourceType="cq/gui/components/authoring/dialog">
    <content jcr:primaryType="nt:unstructured"
             sling:resourceType="granite/ui/components/coral/foundation/container">
        <items jcr:primaryType="nt:unstructured">
            <tabs
                    jcr:primaryType="nt:unstructured"
                    sling:resourceType="granite/ui/components/coral/foundation/tabs"
                    maximized="true">
                <items jcr:primaryType="nt:unstructured">
                    <configuration
                            jcr:primaryType="nt:unstructured"
                            jcr:title="Configuration"
                            sling:resourceType="granite/ui/components/coral/foundation/fixedcolumns"
                            margin="true">
                        <items jcr:primaryType="nt:unstructured">
                            <column
                                    jcr:primaryType="nt:unstructured"
                                    sling:resourceType="granite/ui/components/coral/foundation/container">
                                <items jcr:primaryType="nt:unstructured">
                                    <slides
                                            jcr:primaryType="nt:unstructured"
                                            sling:resourceType="granite/ui/components/coral/foundation/form/multifield"
                                            composite="{Boolean}true"
                                            fieldLabel="Slides">
                                        <field
                                                jcr:primaryType="nt:unstructured"
                                                sling:resourceType="granite/ui/components/coral/foundation/container"
                                                name="./slides">
                                            <items jcr:primaryType="nt:unstructured">
                                                <column
                                                        jcr:primaryType="nt:unstructured"
                                                        sling:resourceType="granite/ui/components/coral/foundation/container">
                                                    <items jcr:primaryType="nt:unstructured">

                                                        <title
                                                                granite:class="cmp-image__editor-alt-text"
                                                                jcr:primaryType="nt:unstructured"
                                                                sling:resourceType="granite/ui/components/coral/foundation/form/textfield"
                                                                fieldLabel="Title"
                                                                name="./title"/>

                                                        <assetConfiguration
                                                                jcr:primaryType="nt:unstructured"
                                                                sling:resourceType="granite/ui/components/coral/foundation/container"
                                                                margin="true">
                                                            <items jcr:primaryType="nt:unstructured">
                                                                <heading
                                                                        granite:class="coral-Heading coral-Heading--4"
                                                                        jcr:primaryType="nt:unstructured"
                                                                        sling:resourceType="granite/ui/components/coral/foundation/heading"
                                                                        level="{Long}4"
                                                                        text="Asset Configuration"/>
                                                                <well
                                                                        jcr:primaryType="nt:unstructured"
                                                                        sling:resourceType="granite/ui/components/coral/foundation/well">
                                                                    <items jcr:primaryType="nt:unstructured">
                                                                        <assetType
                                                                                granite:class="cq-dialog-dropdown-showhide-multival"
                                                                                jcr:primaryType="nt:unstructured"
                                                                                sling:resourceType="granite/ui/components/coral/foundation/form/select"
                                                                                fieldLabel="Asset Type"
                                                                                name="./assetType">
                                                                            <granite:data
                                                                                    jcr:primaryType="nt:unstructured"
                                                                                    cq-dialog-dropdown-showhide-target=".list-option-listfrom-showhide-target-asset-type"/>
                                                                            <items jcr:primaryType="nt:unstructured">
                                                                                <image
                                                                                        jcr:primaryType="nt:unstructured"
                                                                                        text="Image"
                                                                                        value="image"/>
                                                                                <video
                                                                                        jcr:primaryType="nt:unstructured"
                                                                                        text="Video"
                                                                                        value="video"/>
                                                                            </items>
                                                                        </assetType>
                                                                        <setImage
                                                                                granite:class="hide list-option-listfrom-showhide-target-asset-type foundation-layout-util-vmargin"
                                                                                jcr:primaryType="nt:unstructured"
                                                                                sling:resourceType="granite/ui/components/coral/foundation/container">
                                                                            <granite:data
                                                                                    jcr:primaryType="nt:unstructured"
                                                                                    showhidetargetvalue="image"/>
                                                                            <items jcr:primaryType="nt:unstructured">
                                                                                <heading
                                                                                        granite:class="coral-Heading coral-Heading--4"
                                                                                        jcr:primaryType="nt:unstructured"
                                                                                        sling:resourceType="granite/ui/components/coral/foundation/heading"
                                                                                        level="{Long}4"
                                                                                        text="Options for Image"/>
                                                                                <well
                                                                                        jcr:primaryType="nt:unstructured"
                                                                                        sling:resourceType="granite/ui/components/coral/foundation/well">
                                                                                    <items jcr:primaryType="nt:unstructured">

                                                                                        <imageConfiguration
                                                                                                jcr:primaryType="nt:unstructured"
                                                                                                sling:resourceType="granite/ui/components/coral/foundation/container"
                                                                                                margin="{Boolean}true">
                                                                                            <items jcr:primaryType="nt:unstructured">
                                                                                                <heading
                                                                                                        granite:class="coral-Heading coral-Heading--4"
                                                                                                        jcr:primaryType="nt:unstructured"
                                                                                                        sling:resourceType="granite/ui/components/coral/foundation/heading"
                                                                                                        level="{Long}4"
                                                                                                        text="Image Configuration"/>
                                                                                                <well
                                                                                                        jcr:primaryType="nt:unstructured"
                                                                                                        margin="{Boolean}true"
                                                                                                        sling:resourceType="granite/ui/components/coral/foundation/well">
                                                                                                    <items jcr:primaryType="nt:unstructured">
                                                                                                        <column
                                                                                                                jcr:primaryType="nt:unstructured"
                                                                                                                sling:resourceType="granite/ui/components/coral/foundation/container">
                                                                                                            <items jcr:primaryType="nt:unstructured">
                                                                                                                <image
                                                                                                                        jcr:primaryType="nt:unstructured"
                                                                                                                        sling:resourceType="granite/ui/components/coral/foundation/form/pathfield"
                                                                                                                        fieldLabel="Insert the Desktop Image"
                                                                                                                        rootPath="/content/dam"
                                                                                                                        name="./fileReference"/>
                                                                                                            </items>
                                                                                                        </column>
                                                                                                    </items>
                                                                                                </well>
                                                                                            </items>
                                                                                        </imageConfiguration>
                                                                                    </items>
                                                                                </well>
                                                                            </items>
                                                                        </setImage>
                                                                        <setVideo
                                                                                granite:class="hide list-option-listfrom-showhide-target-asset-type foundation-layout-util-vmargin"
                                                                                jcr:primaryType="nt:unstructured"
                                                                                sling:resourceType="granite/ui/components/coral/foundation/container">
                                                                            <granite:data
                                                                                    jcr:primaryType="nt:unstructured"
                                                                                    showhidetargetvalue="video"/>
                                                                            <items jcr:primaryType="nt:unstructured">
                                                                                <heading
                                                                                        granite:class="coral-Heading coral-Heading--4"
                                                                                        jcr:primaryType="nt:unstructured"
                                                                                        sling:resourceType="granite/ui/components/coral/foundation/heading"
                                                                                        level="{Long}4"
                                                                                        text="Options for Video"/>
                                                                                <well
                                                                                        jcr:primaryType="nt:unstructured"
                                                                                        sling:resourceType="granite/ui/components/coral/foundation/well">
                                                                                    <items jcr:primaryType="nt:unstructured">
                                                                                        <videoId
                                                                                                jcr:primaryType="nt:unstructured"
                                                                                                sling:resourceType="granite/ui/components/coral/foundation/form/textfield"
                                                                                                fieldLabel="Video Id (Youtube Video)"
                                                                                                name="./videoId"
                                                                                                required="{Boolean}false">
                                                                                        </videoId>
                                                                                    </items>
                                                                                </well>
                                                                            </items>
                                                                        </setVideo>
                                                                    </items>
                                                                </well>
                                                            </items>
                                                        </assetConfiguration>
                                                    </items>
                                                </column>
                                            </items>
                                        </field>
                                    </slides>
                                </items>
                            </column>
                        </items>
                    </configuration>
                </items>
            </tabs>
        </items>
    </content>
</jcr:root>

This is a very simple dialog, it’s just to show you how it works. How to use it:

  • add your clientlib category in the “extraClientlib” property, as shown above.
  • add the class “cq-dialog-dropdown-showhide-multival” to your dropdown (see assetType)
  • add the data attribute “cq-dialog-dropdown-showhide-multiple-target” to the dropdown/select element, value should be the selector, usually a specific class name, to find all possible target elements that can be shown/hidden (see assetType).
  • add the target class to each target component that can be shown/hidden, add the class hidden to each target component to make them initially hidden and add the attribute showhidetargetvalue to each target component, the value(or commma separated multiple values e.g. val1, val2) should equal the value of the select. (see setImage and setVideo containers)

Now create the clientlib. Choose the category name you prefer and add the following JS file:

/**
 * Extension to the standard dropdown/select component. It enabled hidding/unhidding of other components based on the
 * selection made in the dropdown/select in multifield and multivalued.
 *
 * How to use:
 *
 * - add the class cq-dialog-dropdown-showhide-multival to the dropdown/select element
 * - add the data attribute cq-dialog-dropdown-showhide-target to the dropdown/select element, value should be the
 *   selector, usually a specific class name, to find all possible target elements that can be shown/hidden.
 * - add the target class to each target component that can be shown/hidden
 * - add the class hidden to each target component to make them initially hidden
 * - add the attribute showhidetargetvalue to each target component, the value(or commma separated multiple values e.g. val1, val2) should equal the value of the select
 *   option that will unhide this element.
 */
(function(document, $) {
    "use strict";

    // when dialog gets injected
    $(document).on("foundation-contentloaded", function(e) {
        // if there is already an inital value make sure the according target element becomes visible
        showHideHandler($(".cq-dialog-dropdown-showhide-multival", e.target));
    });

    $(document).on("selected", ".cq-dialog-dropdown-showhide-multival", function(e) {
        showHideHandler($(this));
    });

    function showHideHandler(el) {
        el.each(function(i, element) {
            if ($(element).is("coral-select")) {
                // handle Coral3 base drop-down
                Coral.commons.ready(element, function(component) {
                    showHide(component, element);
                    component.on("change", function() {
                        showHide(component, element);
                    });
                });
            } else {
                // handle Coral2 based drop-down
                var component = $(element).data("select");
                if (component) {
                    showHide(component, element);
                }
            }
        })
    }

    function showHide(component, element) {
        // get the selector to find the target elements. its stored as data-.. attribute
        var target = $(element).data("cqDialogDropdownShowhideTarget");
        var $target = $(target);
        var elementIndex = $(element).closest('coral-multifield-item').index();

        if (target) {
            var value;
            if (component.value) {
                value = component.value;
            } else {
                value = component.getValue();
            }
            $target.each(function(index) {
                var tarIndex = $(this).closest('coral-multifield-item').index();
                if (elementIndex == tarIndex) {
                    $(this).not(".hide").addClass("hide");
                    $(this).filter(function() {
                        return $(this).data('showhidetargetvalue').replace(/ /g, '').split(',').includes(value);
                    }).removeClass("hide");
                }
            });
        }
    }

})(document, Granite.$);

That’s all! This has been tested on AEM 6.5 but I’m pretty sure that can work on AEM 6.4 and 6.3.

Cheers! 🍻

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: