Thursday 17 January 2019

Touch UI - Hide/Show fields inside coral-3 multifield in AEM by coral dropdown

This post shows how to hide/show fields inside multifield in the Touch UI dialog of AEM.
The resourceType used here for composite multifield, selection dropdown, textfield and numberfield are coral 3 ui components. For ex: granite/ui/components/coral/foundation/form/multifield and it has been tested in aem 6.3.

This method uses granite:class attribute added as property to add class in the fields and granite:data node with data key-value added as property to add data attributes in the fields.
Implemented 4 steps are mentioned below: 

1. Add granite:class attribute to the selection field as shown below
 granite:class : cq-dialog-dropdown-showhide1


2. Add granite:data node inside selection field with data key-value added as property as shown below:
cq-dialog-dropdown-showhide-target1 : .list-option-listfrom-showhide-target



3. Add granite:class attribute to each of the fields which you want to show/hide based on 
dropdown selection which matches the data-target attribute of selection field as shown below:
granite:class : list-option-listfrom-showhide-target1


4. Add granite:data node inside each of the fields which you want to show/hide with showhidetargetvalue key 
and value equal to dropdown options value as shown below:
  showhidetargetvalue : textval



To avoid any confusion, the cq_dialog xml i created is pasted below-

<?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:cq="http://www.day.com/jcr/cq/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="Multi ShowHide Component"
    sling:resourceType="cq/gui/components/authoring/dialog"
    helpPath="https://www.adobe.com/go/aem6_3_docs_component_en#Image - HTL">
    <content
        jcr:primaryType="nt:unstructured"
        sling:resourceType="granite/ui/components/foundation/container">
        <layout
            jcr:primaryType="nt:unstructured"
            sling:resourceType="granite/ui/components/foundation/layouts/tabs"
            type="nav"/>
        <items jcr:primaryType="nt:unstructured">
            <multi
                jcr:primaryType="nt:unstructured"
                jcr:title="Multi"
                sling:resourceType="granite/ui/components/foundation/section">
                <layout
                    jcr:primaryType="nt:unstructured"
      sling:resourceType="granite/ui/components/foundation/layouts/fixedcolumns"
                    margin="{Boolean}false"/>
                <items jcr:primaryType="nt:unstructured">
                    <custom
                        jcr:primaryType="nt:unstructured"
      sling:resourceType="granite/ui/components/foundation/container">
                        <items jcr:primaryType="nt:unstructured">
                            <heading
                                jcr:primaryType="nt:unstructured"
      sling:resourceType="granite/ui/components/foundation/heading"
                                class="coral-Heading coral-Heading--4"
                                level="{Long}4"
                                text="Composite Multifield"/>
                            <well
                                jcr:primaryType="nt:unstructured"
      sling:resourceType="granite/ui/components/foundation/container">
                                <layout
                                    jcr:primaryType="nt:unstructured"
      sling:resourceType="granite/ui/components/foundation/layouts/well"/>
                                <items jcr:primaryType="nt:unstructured">
                                    <fieldenter
                                        jcr:primaryType="nt:unstructured"
      sling:resourceType="granite/ui/components/coral/foundation/form/multifield"
                                        composite="{Boolean}true">
                                        <field
                                            jcr:primaryType="nt:unstructured"
      sling:resourceType="granite/ui/components/coral/foundation/container"
                                            fieldLabel="Products Container"
                                            name="./products">
      <items jcr:primaryType="nt:unstructured">
                                            <listFromMulti
      granite:class="cq-dialog-dropdown-showhide1"
                                            jcr:primaryType="nt:unstructured"
      sling:resourceType="granite/ui/components/coral/foundation/form/select"
                                            fieldLabel="Select Multi showhide"
                                            name="listFromMulti">
      <items jcr:primaryType="nt:unstructured">
                                            <text
                                            jcr:primaryType="nt:unstructured"
                                            text="Text field"
                                            value="textval"/>
                                            <num
                                            jcr:primaryType="nt:unstructured"
                                            text="Num field"
                                            value="numval"/>
                                            </items>
                                            <granite:data
                                            jcr:primaryType="nt:unstructured"
      cq-dialog-dropdown-showhide-target1=".list-option-listfrom-showhide-target1"/>
                                            </listFromMulti>
                                            <multitext
      granite:class="list-option-listfrom-showhide-target1"
                                            jcr:primaryType="nt:unstructured"
      sling:resourceType="granite/ui/components/coral/foundation/form/textfield"
                                              fieldLabel="Multi Text"
                                              name="multitext"
                                              showhidetargetvalue="textval">
                                              <granite:data
                                                jcr:primaryType="nt:unstructured"
                                                showhidetargetvalue="textval"/>
                                              </multitext>
                                              <multinum
      granite:class="list-option-listfrom-showhide-target1"
                                              jcr:primaryType="nt:unstructured"
      sling:resourceType="granite/ui/components/coral/foundation/form/numberfield"
                                              fieldLabel="Multi Num"
                                               name="multinum"
                                               showhidetargetvalue="numval">
                                               <granite:data
                                               jcr:primaryType="nt:unstructured"
                                               showhidetargetvalue="numval"/>
                                               </multinum>
                                            </items>
                                        </field>
                                    </fieldenter>
                                </items>
                            </well>
                        </items>
                    </custom>
                </items>
            </multi>
        </items>
    </content>
</jcr:root>

Now to toggle fields using selection dropdown inside composite multifield independently, use below jquery logic 
written in a js file inside clientlibs folder of component with category cq.authoring.dialog .
 
(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-showhide1", e.target));
    });

    $(document).on("change", ".cq-dialog-dropdown-showhide1", function(e) {
        showHideHandler($(this));
    });

    function showHideHandler(el) {
        el.each(function(i, element) {
                // handle Coral3 base drop-down
                Coral.commons.ready(element, function(component) {
                    showHideCustom(component, element);
                    component.on("change", function() {
                        showHideCustom(component, element);
                    });
                });
        })
    }

    function showHideCustom(component, element) {
         // get the selector to find the target elements. 
         //its stored as data-.. attribute
       var target = $(element).data("cq-dialog-dropdown-showhide-target1");
       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();
         }
         $(element).closest("coral-multifield-item").find(target)
         .each(function(index) {
            var tarIndex = $(this).closest('coral-multifield-item').index();
            if (elementIndex == tarIndex) {
                $(this).not(".hide").parent().addClass("hide");
                $(this).filter("[data-showhidetargetvalue='" + value + "']")
                .parent().removeClass("hide");
            }
         });
        }
    }

})(document, Granite.$);

The screenshot of how the dialog looks like and how it toggle fields is shown below- 


You can also find this component in my github project here .