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?
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.