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 .

5 comments:

  1. Thanks for sharing. Its working for simple multifield but not in nested multifield. Any inputs for showhide in nested multifield?

    ReplyDelete
  2. I don't understand why is '1' at the end: granite:class : cq-dialog-dropdown-showhide1. Can you tell me?

    ReplyDelete
    Replies
    1. There’s no significance of ‘1’, it can be any variable(you have to do corresponding change in js as well). Just that it has to be different from ootb show hide class selector- cq-dialog-dropdown-showhide-target which doesn’t work inside multifield.

      Delete