Granite UI Multifield Sightly Traverse | Iterate Simple Example

In this article, we will share an example on on how we can iterate and traverse through multifield nodes that have been generated by the Touch UI using Sightly in a very simple way.

Going through this article, we will be setting up multifield Granite UI links (as if we are building a menu navigation). Each link will define it’s own path, label, and target. Take a look at both screenshots below. One screenshot indicates how a multifield Granite UI field will look like, and in the second screenshot displays how saved nodes would look like in the crx/de console.

Touch UI - show casing multifield link configurations screenshot
CRX/DE saved link nodes from the Touch UI screenshot


Step 1. Touch UI Configuration

Putting together a very basic Touch UI configuration using tabs to organize our Granite UI fields. Here we will place the entire configuration under:
/apps/sourcedcode/components/content/multilistexample/_cq_dialog/.content.xml.

line: 34, declaring a multifield
line: 42, declaring multifield > label
line: 48, declaring multifield > path
line: 55, declaring multifield > target

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
<?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="Multi List Example"
   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">
            <generalSettings
               jcr:primaryType="nt:unstructured"
               jcr:title="General Settings"
               sling:resourceType="granite/ui/components/foundation/section">
                <layout
                   jcr:primaryType="nt:unstructured"
                   sling:resourceType="granite/ui/components/foundation/layouts/fixedcolumns"
                   type="nav"/>
                <items jcr:primaryType="nt:unstructured">
                    <column
                       jcr:primaryType="nt:unstructured"
                       sling:resourceType="granite/ui/components/coral/foundation/container">
                        <items jcr:primaryType="nt:unstructured">
                            <linkOptions
                               jcr:primaryType="nt:unstructured"
                               jcr:title="Links Options"
                               sling:resourceType="granite/ui/components/coral/foundation/form/fieldset">
                                <items jcr:primaryType="nt:unstructured">
                                    <links
                                       jcr:primaryType="nt:unstructured"
                                       sling:resourceType="granite/ui/components/coral/foundation/form/multifield"
                                       composite="{Boolean}true"
                                       fieldLabel="Links">
                                        <field
                                           jcr:primaryType="nt:unstructured"
                                           sling:resourceType="granite/ui/components/coral/foundation/container"
                                           name="./links">
                                            <items jcr:primaryType="nt:unstructured">
                                                <linkLabel
                                                   jcr:primaryType="nt:unstructured"
                                                   sling:resourceType="granite/ui/components/coral/foundation/form/textfield"
                                                   fieldLabel="Link Label"
                                                   name="./linkLabel"
                                                   required="true"/>
                                                <linkPath
                                                   jcr:primaryType="nt:unstructured"
                                                   sling:resourceType="granite/ui/components/coral/foundation/form/pathfield"
                                                   fieldLabel="Link Path"
                                                   name="./linkPath"
                                                   required="true"
                                                   rootPath="/content"/>
                                                <linkTarget
                                                   jcr:primaryType="nt:unstructured"
                                                   sling:resourceType="granite/ui/components/coral/foundation/form/select"
                                                   fieldLabel="Link Target"
                                                   name="./linkTarget">
                                                    <items jcr:primaryType="nt:unstructured">
                                                        <self
                                                           jcr:primaryType="nt:unstructured"
                                                           selected="{Boolean}true"
                                                           text="Same Page"
                                                           value="_self"/>
                                                        <blank
                                                           jcr:primaryType="nt:unstructured"
                                                           text="New Tab"
                                                           value="_blank"/>
                                                    </items>
                                                </linkTarget>
                                            </items>
                                        </field>
                                    </links>
                                </items>
                            </linkOptions>
                        </items>
                    </column>
                </items>
            </generalSettings>
        </items>
    </content>
</jcr:root>

Step 2. Sightly HTL Front-end

A very simple way to get a list of objects to iterate through will be to use Sling Model’s backend and Sling Specific Annotations. Together the mechanism combined will enable the Sightly HTL code to receive a List, which you can use this list to iterate through each item, to display nav link configurations that were set by the authors.

Using the Sightly data-sly-list API, we can traverse through each item from the List. Iterating through each item returns an Resource.class onbject, which it has a getValueMap() public getter method. With this getter method we can get the valueMap object and reveal the configurations that are set by the authors.

1
2
3
4
5
6
7
8
<div class="cmp-multilistexample"
    data-sly-use.cmp="com.sourcedcode.core.models.content.MultiListExample">
  <sly data-sly-list.link="${cmp.links}">
    <li>
      <a href="${link.valueMap.linkPath}" target="${link.valueMap.linkTarget}" rel="noopener">${link.valueMap.linkLabel}</a>
    </li>
  </sly>
</div>

Step 3. Sling Model Java Backend

Sling Model’s backend and Sling Specific Annotations. Together the mechanism combined will enable the Sightly HTL code to receive a List.

Pro Tip:
Decrease your AEM development time using our AEM Sling Model Cheat Sheet Reference Guide! View Guide.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package com.sourcedcode.core.models.content;

import lombok.Getter;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.models.annotations.DefaultInjectionStrategy;
import org.apache.sling.models.annotations.Model;
import org.apache.sling.models.annotations.injectorspecific.ChildResource;

import javax.inject.Named;
import java.util.List;

@Model(adaptables = Resource.class,
        defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL)
public class MultiListExample {
    @Getter
    @ChildResource
    @Named("links")
    private List<Resource> links;
}

Step 4. Results

Work your maven magic, and build the code. Once your backend bundle and Sightly HTL code are aligned, you should be able to see the links like here in the screenshot.
Links Results


Hello, I am an enthusiastic Adobe Community Advisor and a seasoned Lead AEM Developer. I am currently serving as an AEM Technical Lead at MNPDigital.ca, bringing over a decade of extensive web engineering experience and more than eight years of practical AEM experience to the table. My goal is to give back to the AEM Full Stack Development community by sharing my wealth of knowledge with others. You can connect with me on LinkedIn.

2 thoughts on “Granite UI Multifield Sightly Traverse | Iterate Simple Example

  1. This is exactly what I am looking for, but I tried to write the Java code it is asking for a setter. Do you have a working package of this code.

Leave a Reply

Your email address will not be published. Required fields are marked *


Back To Top