0

I have created a component with a design dialog and policy. I can read basic properties of the design dialog but am confused on what to do with multifield.

Design dialog (check headerPrimaryLinks)

<?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="Header"
    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">
                    <properties
                        jcr:primaryType="nt:unstructured"
                        jcr:title="Main"
                        sling:resourceType="granite/ui/components/coral/foundation/container"
                        margin="{Boolean}true">
                        <items jcr:primaryType="nt:unstructured">
                            <heading
                                jcr:primaryType="nt:unstructured"
                                sling:resourceType="granite/ui/components/coral/foundation/form/textfield"
                                fieldLabel="Heading"
                                name="./heading"/>
                            <logoAltText
                                jcr:primaryType="nt:unstructured"
                                sling:resourceType="granite/ui/components/coral/foundation/form/textfield"
                                fieldLabel="Logo Alt Text"
                                name="./alttext"/>
                        </items>
                    </properties>
                    <!-- <styletab
                        jcr:primaryType="nt:unstructured"
                        sling:resourceType="granite/ui/components/coral/foundation/include"
                        path="/mnt/overlay/cq/gui/components/authoring/dialog/style/tab_design/styletab"/> -->
                    <primaryLinks
                        jcr:primaryType="nt:unstructured"
                        jcr:title="Primary Links"
                        sling:resourceType="granite/ui/components/coral/foundation/container"
                        margin="{Boolean}true">
                        <items jcr:primaryType="nt:unstructured">
                            <link
                                jcr:primaryType="nt:unstructured"
                                sling:resourceType="granite/ui/components/coral/foundation/form/multifield"
                                composite="{Boolean}true"
                                fieldDescription="Click '+' to add a new link">
                                <field
                                    jcr:primaryType="nt:unstructured"
                                    sling:resourceType="granite/ui/components/coral/foundation/form/fieldset"
                                    name="./headerPrimaryLinks">
                                    <items jcr:primaryType="nt:unstructured">
                                        <column
                                            jcr:primaryType="nt:unstructured"
                                            sling:resourceType="granite/ui/components/coral/foundation/container">
                                            <items jcr:primaryType="nt:unstructured">
                                                <title
                                                    jcr:primaryType="nt:unstructured"
                                                    sling:resourceType="granite/ui/components/coral/foundation/form/textfield"
                                                    fieldLabel="Title"
                                                    name="./title"/>
                                                <linkURL
                                                    jcr:primaryType="nt:unstructured"
                                                    sling:resourceType="granite/ui/components/coral/foundation/form/pathbrowser"
                                                    fieldLabel="Link to"
                                                    name="./linkURL"
                                                    rootPath="/content"/>
                                            </items>
                                        </column>
                                    </items>
                                </field>
                            </link>
                        </items>
                    </primaryLinks>
                </items>
            </tabs>
        </items>
    </content>
</jcr:root>

Header.java class

import javax.annotation.PostConstruct;

import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ValueMap;
import org.apache.sling.models.annotations.Model;
import org.apache.sling.models.annotations.injectorspecific.Self;
import org.apache.sling.models.annotations.injectorspecific.SlingObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.day.cq.wcm.api.policies.ContentPolicy;
import com.day.cq.wcm.api.policies.ContentPolicyManager;

@Model(adaptables = Resource.class)
public class Header {
    private final Logger logger = LoggerFactory.getLogger(getClass());

    @SlingObject
    private ResourceResolver resourceResolver;

    @Self
    protected Resource resource;

    private String heading,
                   altText;

    @PostConstruct
    protected void init() {
        ContentPolicyManager policyManager = resourceResolver.adaptTo(ContentPolicyManager.class);

        if (policyManager != null) {
            ContentPolicy contentPolicy = policyManager.getPolicy(resource);

            if (contentPolicy != null) {
                ValueMap properties = contentPolicy.getProperties();

                // I can read these fine but how do I read a multifield?
                heading = (String) properties.get("heading");
                altText = (String) properties.get("alttext");
            }
        }
    }

    /**
    * Returns heading from design dialog.
    * 
    * @return heading
    */
    public String getHeading() {
        return heading;
    }

    /**
    * Returns alttext (logo alt text) from design dialog.
    * 
    * @return altText
    */
    public String getAltText() {
        return altText;
    }
}

In the component, I can read Strings like:

<sly data-sly-use.header="com.uchealth.aem.core.models.Header">
    ${header.heading}
</sly>

or just

${currentStyle.heading}

Here is how it looks in CRX:

header
-  policy_1547171225060
    - headerPrimaryLinks
      - item0
      - item1
      - item2
    - headerSecondaryLinks
      - item0
      - item1
      - item2

How do I read a multifield to use data-sly-list in my HTL?

Evan Borden
  • 11
  • 1
  • 5
  • Sling model implementation is pretty much same in 6.3 and 6.4. So, please check this example -https://stackoverflow.com/questions/46516703/aem-6-3-multifield-using-sling-model – phemanthkumar28 Jan 14 '19 at 18:11
  • Correct, but that example is referencing a regular dialog not a design dialog. Do you know how to do this with a design dialog and policy? – Evan Borden Jan 14 '19 at 19:01

1 Answers1

2

I have not tested this, so I'm not sure it works 100%. First of all, you will need a SlingModel to represent the multifield items:

@Model(adaptables = Resource.class)
public class HeaderPrimaryLink {

    @Inject
    private Resource resource;

    @Inject
    @Optional
    private String title;

    @Inject
    @Optional
    private String linkURL;

    public String getTitle() {
        return title;
    }

    public String getLinkURL() {
        return linkURL;
    }
}

Then, in your "Header" model you can have a list of "HeaderPrimaryLink" models that will contain all the items filled in the multifield:

...
    private String heading,
               altText;

    private List<HeaderPrimaryLink> links;

    @PostConstruct
...

I'm not sure how is the multifield being stored under the policy node (if you can post an image of the nodes in the CRX would help), but assuming the multifield is stored as nodes under the policy resource, I would try to get that node and fill the list (something like this):

    Resource multifieldResource = resourceResolver.getResource(contentPolicy.getPath() + "/headerPrimaryLinks");
    if (multifieldResource != null) {
        for (Resource currentResource : multifieldResource.getChildren()) {
            links.add(currentResource.adaptTo(HeaderPrimaryLink.class));
        }
    }

And then in the HTML:

<sly data-sly-use.header="com.uchealth.aem.core.models.Header">
    <ul data-sly-list="${header.links}">
        <li>
           <a target="_blank" href="${item.linkURL}">${item.title}</a>
        </li>
    </ul>
</sly>

Hope that helps.

Evaristo Carmona
  • 306
  • 1
  • 12
  • I edited my post to give the hierarchy is it looks in CRX. I think we are on to something here. I've tried the above code but get SlingException when trying to adapt **currentResource** to **HeaderPrimaryLink.class**. – Evan Borden Jan 15 '19 at 14:48
  • I figured it out. I did not instantiate a new ArrayList for **links** so **links** was receiving a nullPointerException as it was trying to add to nothing. Simple mistake. Thank you! – Evan Borden Jan 15 '19 at 15:29