Showing posts with label Multifield. Show all posts
Showing posts with label Multifield. Show all posts

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 .

Sunday, 8 April 2018

Retrieve Composite Multifield child values in AEM through Java (WCMUsePojo)

This post is a part 2 of my previous blog Composite Collapsible Multifield in AEM 6.3 Touch UI in which we retrieved the authored multifield values in our sightly code by using JS Use-API.

Here, we'll use the Java WCMUsePojo API to retrieve the multifield child values in our sightly code.

Since the multifield values stored in the page is stored as child nodes as shown below:





First, we'll create the MultiList bean having same properties as in our dialog with getters and setters as shown below:

package com.foo.community.core;

public class MultiList {
 
 private String multitext;
 private String multinum;
 private String multicheck;

 public String getMultitext() {
  return multitext;
 }

 public void setMultitext(String multitext) {
  this.multitext = multitext;
 }

 public String getMultinum() {
  return multinum;
 }

 public void setMultinum(String multinum) {
  this.multinum = multinum;
 }

 public String getMulticheck() {
  return multicheck;
 }

 public void setMulticheck(String multicheck) {
  this.multicheck = multicheck;
 }
}

And then, we'll create a class extending WCMUsePojo where we'll get the current node and then get the products node (where child values of multifield are stored) and iterate over that and set the retrieved property values in List of MultiList bean created above. Below is the implementation of this process:

package com.foo.community.core;

import java.util.ArrayList;
import java.util.List;   
import com.adobe.cq.sightly.WCMUsePojo;
import javax.jcr.Node;
import javax.jcr.NodeIterator;    

public class MultiListComponent extends WCMUsePojo{

  private List multiItems = new ArrayList();

  @Override
  public void activate() throws Exception {

     Node currentNode = getResource().adaptTo(Node.class);
     if(currentNode.hasNode("products")){
     Node productsNode = currentNode.getNode("products");
     NodeIterator ni =  productsNode.getNodes();
     
     String multitext;
     String multinum;
     String multicheck;

     while (ni.hasNext()) {

      MultiList multiItem = new MultiList();          
      Node child = (Node)ni.nextNode();

         multitext= child.hasProperty("multitext") ? 
           child.getProperty("multitext").getString(): ""; 
         multinum = child.hasProperty("multinum") ? 
           child.getProperty("multinum").getString(): ""; 
         multicheck = child.hasProperty("multicheck") ? 
           child.getProperty("multicheck").getString(): "";    
     
         multiItem.setMultitext(multitext);
         multiItem.setMultinum(multinum);
         multiItem.setMulticheck(multicheck);
         multiItems.add(multiItem);
     }  
    }
 } 

 public List getMultiItems() {
  return multiItems;
 }
}

And use below sightly code (blog.html) to render values in the html:

<div data-sly-use.blog="com.foo.community.core.MultiListComponent">
  <h4>Composite Multifield</h4>
  <ol data-sly-list.product="${blog.multiItems}">
     <li>
        ${product.multitext} has ${product.multinum} with boolean 
        ${product.multicheck}
     </li>
  </ol>
</div>

Saturday, 7 April 2018

Composite Collapsible Multifield in AEM 6.3 Touch UI

This post discusses how to create a composite collapsible multifield touch ui dialog which uses Granite UI Coral3 multifield in AEM 6.3 .

We'll be using OOTB coral multifield provided by AEM 6.3 for storing multifield values as child nodes (NODE STORE)granite/ui/components/coral/foundation/form/multifield, and we'll retrieve the authored multifield values in our sightly code by using JS Use-API (To retrieve values via WCMUsePojo API, refer this post here).

The advantage of using JS Use-API here is you can get the node of multifield values stored in pages and pass it to the sightly code in few lines of code as compared to more lines of code when using JAVA for this.

Also you won't need to use acs-commons package or any other custom multifield here for storing composite multifield values.

To make the multi-fields collapsible we'll be using the foundation layout type inside container as: granite/ui/components/foundation/layouts/collapsible, thus we would not need to write customization code in clientlibs for this.

The touch ui dialog structure is shown below:

<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/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="Blog 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">
                    <column
                        jcr:primaryType="nt:unstructured"                       
       sling:resourceType="granite/ui/components/foundation/container">
                        <items jcr:primaryType="nt:unstructured">
                            <fieldenter
                                jcr:primaryType="nt:unstructured"
       sling:resourceType="granite/ui/components/coral/foundation/form/multifield"
                                composite="{Boolean}true"
                                fieldLabel="Composite Multifield">
                                <field
                                    jcr:primaryType="nt:unstructured"
                                    jcr:title="Click to Expand"                              
       sling:resourceType="granite/ui/components/foundation/container"
                                    fieldLabel="Products Container"
                                    name="./products">
                                    <layout
                                     jcr:primaryType="nt:unstructured"                                 
       sling:resourceType="granite/ui/components/foundation/layouts/collapsible"/>
                                    <items 
                                     jcr:primaryType="nt:unstructured">
                                        <multitext
                                            jcr:primaryType="nt:unstructured"
       sling:resourceType="granite/ui/components/foundation/form/textfield"
                                            fieldLabel="Multi Text"
                                            name="multitext"/>
                                        <multinum
                                            jcr:primaryType="nt:unstructured"
       sling:resourceType="granite/ui/components/foundation/form/numberfield"
                                            fieldLabel="Multi Num"
                                            name="multinum"/>
                                        <multicheck
                                            jcr:primaryType="nt:unstructured"               
       sling:resourceType="granite/ui/components/foundation/form/checkbox"
                                            name="multicheck"
                                            text="Multi Check"
                                            value="{Boolean}true"/>
                                    </items>
                                </field>
                            </fieldenter>
                        </items>
                    </column>
                </items>
            </multi>
        </items>
    </content>
</jcr:root>

Touch UI Dialog authoring interface is as shown below:


The multifield values stored in the page is stored as child nodes as shown below:





You can use below JS Use code (blog.js) to fetch the node and pass to sightly:

"use strict";
use(function() {
    var resourceResolver = resource.getResourceResolver();
    return {
      node : resourceResolver.getResource(currentNode.getPath() + "/products"),
    };
});

And use below sightly code (blog.html) to render values in the html:

<div data-sly-use.blog="blog.js">
    <h4>Composite Multifield Values: </h4>
    <ol data-sly-list.product="${blog.node.listChildren}">
      <li>
          ${product.multitext} has ${product.multinum} with boolean 
          ${product.multicheck}
      </li>
    </ol>
</div>