Nested Multifield AEM 6.5

Nested Coral Multifield in AEM 6.5

Goal

Create a component that uses a nested multifield as simple as possible.

Procedure

Let’s create our dialog as follows:

<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/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="Nested Accordion"
      sling:resourceType="cq/gui/components/authoring/dialog">
    <content
        jcr:primaryType="nt:unstructured"
        sling:resourceType="granite/ui/components/coral/foundation/container">
        <items
            jcr:primaryType="nt:unstructured">
            <tabs
                jcr:primaryType="nt:unstructured"
                sling:resourceType="granite/ui/components/coral/foundation/tabs"
                maximized="{Boolean}true">
                <items
                    jcr:primaryType="nt:unstructured">
                    <componentProperties
                        jcr:primaryType="nt:unstructured"
                        sling:resourceType="granite/ui/components/coral/foundation/container"
                        jcr:title="Component Properties">
                        <items
                            jcr:primaryType="nt:unstructured">
                            <columns
                                jcr:primaryType="nt:unstructured"
                                sling:resourceType="granite/ui/components/coral/foundation/fixedcolumns">
                                <items
                                    jcr:primaryType="nt:unstructured">
                                    <column
                                        jcr:primaryType="nt:unstructured"
                                        sling:resourceType="granite/ui/components/coral/foundation/container"
                                        margin="{Boolean}true">
                                        <items
                                            jcr:primaryType="nt:unstructured">
                                            <title
                                                jcr:primaryType="nt:unstructured"
                                                fieldLabel="Title"
                                                sling:resourceType="granite/ui/components/coral/foundation/form/textfield"
                                                emptyText="Title"
                                                name="./title"/>
                                            <accordions
                                                jcr:primaryType="nt:unstructured"
                                                sling:resourceType="granite/ui/components/coral/foundation/form/multifield"
                                                composite="{Boolean}true"
                                                fieldLabel="Accordions">
                                                <field
                                                    jcr:primaryType="nt:unstructured"
                                                    sling:resourceType="granite/ui/components/coral/foundation/container"
                                                    name="./accordions">
                                                    <items jcr:primaryType="nt:unstructured">
                                                        <title
                                                            jcr:primaryType="nt:unstructured"
                                                            fieldLabel="Accordion Title"
                                                            sling:resourceType="granite/ui/components/coral/foundation/form/textfield"
                                                            emptyText="Title"
                                                            name="./title"/>
                                                        <list
                                                            jcr:primaryType="nt:unstructured"
                                                            sling:resourceType="granite/ui/components/coral/foundation/form/multifield"
                                                            composite="{Boolean}true"
                                                            fieldLabel="Bullet list">
                                                            <field
                                                                jcr:primaryType="nt:unstructured"
                                                                sling:resourceType="granite/ui/components/coral/foundation/container"
                                                                name="./list">
                                                                <items jcr:primaryType="nt:unstructured">
                                                                    <description
                                                                        fieldLabel="Description Label"
                                                                        jcr:primaryType="nt:unstructured"
                                                                        sling:resourceType="granite/ui/components/coral/foundation/form/textfield"
                                                                        emptyText="Description"
                                                                        name="./description"/>
                                                                </items>
                                                            </field>
                                                        </list>
                                                    </items>
                                                </field>
                                            </accordions>
                                        </items>
                                    </column>
                                </items>
                            </columns>
                        </items>
                    </componentProperties>
                </items>
            </tabs>
        </items>
    </content>
</jcr:root>

The outer multfield starts with the tag “accordions”, while the inner multifield starts with the tag “list”.

The dialog layout is the following:

This is how our data will be stored in the CRX:

And this is our data will be displayed, obviously I’m not using any kind of css style:

The HTL file I used. In this case I preferred to use a Sling Model to retrieve our data

<sly data-sly-use.accordion="${'com.adobe.training.core.models.accordion.AccordionListModel'}"></sly>
<sly data-sly-test.configured="${accordion.configured}"></sly>
<sly data-sly-test="${wcmmode.edit && !configured}">
    <div data-emptytext="${component.title}" class="cq-placeholder"></div>
</sly>
<div data-sly-test="${configured}">
    <h2 class="accordion__title js-accordion-title">${accordion.title}</h2>
    <div class="" data-sly-list.accordions="${accordion.accordionList}">
        <h4> ${accordions.title}</h4>
        <ul data-sly-list="${accordions.bulletPointList}">
            <li class="accordion__text">${item.description @ context='html'}</li>
        </ul>
    </div>
</div>

Let’s go in deep and have a look to the Java Code. The main model used in the HTL file, “AccordionListModel”, is the following

package com.adobe.training.core.models.accordion;

import org.apache.sling.api.resource.Resource;
import org.apache.sling.models.annotations.DefaultInjectionStrategy;
import org.apache.sling.models.annotations.Model;

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

@Model(adaptables = Resource.class, defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL)
public class AccordionListModel {

    @Inject
    private String title;

    @Inject
    @Named("accordions/.")
    public List<AccordionModel> accordionList;

    public List<AccordionModel> getAccordionList() {
        return accordionList;
    }

    public String getTitle() {
        return title;
    }

    public boolean isConfigured() {
        return accordionList != null && !accordionList.isEmpty();
    }

}

Similarly to the other article, I’ve injected properties and children resources (using the annotation @Named(“accordions/.”)). And instead of injecting a list of Resource, I preferred to inject immediately the adapted model so that you can easily access to its properties in the HTL code.

Since in this case we are using a nested multifield, the model “AccordionBulletPointModel” (the outer multifield) will follow the same logic:

package com.adobe.training.core.models.accordion;

import org.apache.sling.api.resource.Resource;
import org.apache.sling.models.annotations.DefaultInjectionStrategy;
import org.apache.sling.models.annotations.Model;

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

@Model(adaptables = Resource.class, defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL)
public class AccordionModel {

    @Inject
    private String title;

    @Inject
    @Named("list/.")
    private List<AccordionBulletPointModel> bulletPointList;

    public String getTitle() {
        return title;
    }

    public List<AccordionBulletPointModel> getBulletPointList() {
        return bulletPointList;
    }

}

And finally our last model, which contains the inner multifield:

package com.adobe.training.core.models.accordion;

import org.apache.sling.api.resource.Resource;
import org.apache.sling.models.annotations.DefaultInjectionStrategy;
import org.apache.sling.models.annotations.Model;

import javax.inject.Inject;

@Model(adaptables = Resource.class, defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL)
public class AccordionBulletPointModel {

    @Inject
    private String description;

    public String getDescription() {
        return description;
    }

}

That’s all! As for the other article, this has been tested on AEM 6.5 but I’m pretty sure that can work on AEM 6.4 and 6.3. I’m not sure in the previous versions because the sling:resourceType will be different (not the coral one).

Of course you can create more complex multifield in order to make the most of your Sling Models.

If you are looking at how to limit the number of items in a multifield have a look here.

Cheers! 🍸

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: