Create Touch UI Nested MultiField Dialog in AEM
In this tutorial we will see how to create Touch UI Nested Multifield component using HTL in aem. This tutorial is in continuation with our last tutorial about creating multifiled component in aem. In this tutorials also we will be using ACS common (Adobe consulting services) multifield component that allows developers to create a nested multifield (multifield inside multifield) of a fieldset (group of different fields) .
Sometimes developer get into a situation where they need to use a nested multifield dialog to meet customer requirement. AEM developers require huge effort till aem 6.2 to create a nested multifiled as it has many issue, but with release of aem 6.3 and stable service pack 1. It is now a matter of couple of minutes to create a nested multifiled.
After completing this tutorial, you will have a clear understanding about:-
- How toĀ Create Nested Touch UI MultiField Component in AEM 6.3 using HTL.
- How to retrieve values from Nested Touch UI Multifield dialog.
Create Nested Touch UI MultiField Component in AEM 6.3 using HTL:-
Lets extend use case of creating a user menu for your website and retrieving its value stored in the form of JSON Array from crxde/JCR repository that we have used in our previous tutorial. Follow below steps to create acs commons nested multi field component :-
- Login to crxde.
- Go to /apps/<project-name>/<path-to-component> [For Ex:- /apps/my-aem-project/components/content/ ]
- Create a new component under content node [For Ex:- In our example nested-userSubMenu]
- Paste below content.xml of our multi field component.
nested-userSubMenu
<?xml version="1.0" encoding="UTF-8"?> <jcr:root xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" jcr:description="Nested Multi Field Example" jcr:primaryType="cq:Component" jcr:title="Nested Multi Field" componentGroup="aemcq5tutorials"/>
cq:dialog content.xml:-
<?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="User Menu" sling:resourceType="cq/gui/components/authoring/dialog"> <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"> <tabs jcr:primaryType="nt:unstructured" jcr:title="General" sling:resourceType="granite/ui/components/foundation/container"> <items jcr:primaryType="nt:unstructured"> <usersubmenu jcr:primaryType="nt:unstructured" jcr:title="User Submenu" sling:resourceType="granite/ui/components/foundation/section"> <layout jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/foundation/layouts/fixedcolumns"/> <items jcr:primaryType="nt:unstructured"> <tab jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/foundation/container"> <items jcr:primaryType="nt:unstructured"> <usersubmenudetails jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/foundation/form/multifield" class="full-width" fieldDescription="Click 'Add field' to add a new User Submenu title and links" fieldLabel="User Submenu Items"> <field jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/foundation/form/fieldset" acs-commons-nested="" name="./myUserSubmenu"> <layout jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/foundation/layouts/fixedcolumns" method="absolute"/> <items jcr:primaryType="nt:unstructured"> <column jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/foundation/container"> <items jcr:primaryType="nt:unstructured"> <title jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/foundation/form/textfield" fieldDescription="Enter User Submenu title" fieldLabel="User Submenu Title" name="./title"/> <link jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/foundation/form/pathbrowser" fieldDescription="Enter User Submenu Link" fieldLabel="User Submenu Link" name="./link" rootPath="/content"/> <usernestedsubmenudetails jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/foundation/form/multifield" class="full-width" fieldDescription="Click 'Add field' to add a new User Submenu title and links" fieldLabel="User Nested Submenu Items"> <field jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/foundation/form/fieldset" acs-commons-nested="" name="./myNestedUserSubmenu"> <layout jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/foundation/layouts/fixedcolumns" method="absolute"/> <items jcr:primaryType="nt:unstructured"> <column jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/foundation/container"> <items jcr:primaryType="nt:unstructured"> <title jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/foundation/form/textfield" fieldDescription="Enter User Nested Submenu title" fieldLabel="User Nested Submenu Title" name="./subtitle"/> </items> </column> </items> </field> </usernestedsubmenudetails> </items> </column> </items> </field> </usersubmenudetails> </items> </tab> </items> </usersubmenu> </items> </tabs> </items> </content> </jcr:root>
Note:- To use acs commons multifield it is mandatory to add acs-commons-nested=”” property to a fieldset within a multifield node Ā like at myUserSubmenu node in our example.Ā acs-commons-nested=”” acs-commons-nested=”JSON_STORE” or means we want to store multifiled data as JSON Array. To store multi filed data as seperate child node useĀ acs-commons-nested=”NODE_STORE”.
cq:editConfig content.xml:-
<?xml version="1.0" encoding="UTF-8"?> <jcr:root xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" jcr:primaryType="cq:EditConfig"> <cq:listeners jcr:primaryType="cq:EditListenersConfig" afteredit="REFRESH_SELF"/> </jcr:root>
dialog.xml
<?xml version="1.0" encoding="UTF-8"?> <jcr:root xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" jcr:primaryType="cq:Dialog" xtype="dialog"/>
Note:- dialog.xml or editConfig.xml is required because if we don’t have dialog in our component then it wont get displayed in side rail of Touch UI.Ā
- After adding these nodes content.xml. Open component rending script or html file [For EX:- nested-userSubMenu.html] and add below code to it.
Click here to configure Nested Multi Field User Menu <div data-sly-use.multiItems="aemlearning.pojo.TouchNestedMultiFieldComponentUse"> <div data-sly-list.head="${multiItems.multiFieldItems}"> <p><b>Page Name:</b> ${head.title}</p> <p><b>Page Path:</b> ${head.link}</p> <p><b>Nested Sub Title:</b> ${head.subtitle}</p> </div> </div>
Now our component structure should look like below screenshot:-
Note:- The only important thing that you have to consider is to use acs-common-nested property on nested multifield node also.Ā
Retrieve values from Nested Multifield dialog:-
Now lets see how to retrieve values stored in jcr for nested multifield component.
Lets create two java fileĀ TouchNestedMultiFieldBean andĀ TouchNestedMultiFieldComponentUse to retrieveĀ values from crxde.
TouchNestedMultiFieldBean.java
package aemlearning.bean; /** * POJO for Nested Multi Field items * * @author aahlawat * */ public class TouchNestedMultiFieldBean { private String title; private String link; private String subtitle; public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getLink() { return link; } public void setLink(String link) { this.link = link; } public String getSubtitle() { return subtitle; } public void setSubtitle(String subtitle) { this.subtitle = subtitle; } }
TouchNestedMultiFieldComponentUse.java
package aemlearning.pojo; import java.util.ArrayList; import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.adobe.cq.sightly.WCMUsePojo; import com.google.gson.Gson; import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import aemlearning.bean.TouchNestedMultiFieldBean; public class TouchNestedMultiFieldComponentUse extends WCMUsePojo { private static final Logger LOGGER = LoggerFactory.getLogger(TouchNestedMultiFieldComponentUse.class); private List<TouchNestedMultiFieldBean> submenuItems = new ArrayList<>(); @Override public void activate() throws Exception { setNestedMultiFieldItems(); } /** * Method to get Multi field data * * @return submenuItems */ private List<TouchNestedMultiFieldBean> setNestedMultiFieldItems() { JsonObject jObj; JsonArray jNestedArr; Gson gson = new Gson(); try { String[] itemsProps = getProperties().get("myUserSubmenu", String[].class); if (itemsProps != null) { for (int i = 0; i < itemsProps.length; i++) { JsonElement json = gson.fromJson(itemsProps[i], JsonElement.class); jObj = json.getAsJsonObject(); TouchNestedMultiFieldBean menuItem = new TouchNestedMultiFieldBean(); String title = jObj.get("title").toString(); String path = jObj.get("link").toString(); jNestedArr = jObj.getAsJsonArray("myNestedUserSubmenu"); if (!jNestedArr.isJsonNull() && jNestedArr.size() > 0) { JsonObject jNestedObj = jNestedArr.get(0).getAsJsonObject(); menuItem.setSubtitle(jNestedObj.get("subtitle").toString()); } menuItem.setTitle(title); menuItem.setLink(path); submenuItems.add(menuItem); } } } catch (Exception e) { LOGGER.error("Exception while Multifield data {}", e.getMessage(), e); } return submenuItems; } public List<TouchNestedMultiFieldBean> getMultiFieldItems() { return submenuItems; } }
That’s it you are done
- Just build the component from eclipse.
- Drag and drop usermenu component on any parsys.
- Enter the values and save it.
Value stored in CRX/JCR in form of JSON Array:-
You can download the code used in above tutorial for creating touch ui nested multifield dialog from my repositoryĀ https://bitbucket.org/aahlawa/aem-learning/branch/nested-multifield
Leave a Reply