Hi All,
I have a JSON for the component which is exported as below -
"componentA": {
":type": "a/b/c",
"test": "Test String.",
"test1": "cf63d10c-5ad7-44d5-9986-e1673b21675c",
"test2": "#E5E5E5",
"test3": "false"
}
However, the component has an inherent logic - The sightly for the component calls a generic model which collects multi-field items as resource and displays its details.
<sly data-sly-use.testList="${'test.abc.core.models.multifieldcollection.MultifieldCollectionModel' @ resourcePath = resource.path , multifieldName='testList'}"
if (resourcePath != null && multifieldName != null) {
String multifieldResourcePath = String.join("/", resourcePath, multifieldName);
ResourceResolver resolver = resource.getResourceResolver();
Resource multifieldResource = resolver.getResource(multifieldResourcePath);
if (multifieldResource != null) {
multifieldResource.listChildren().forEachRemaining(multiCollection::add);
}
}
As you can see this helps fetches all the multi-field items but doesn't extend the same to JSON as there is no way to export this as @JsonProperty.
What should be the best way to export these items as part of the component's JSON?
Thanks,
NR
Topics help categorize Community content and increase your ability to discover relevant content.
Views
Replies
Total Likes
Hi @NageshRaja,
You’ll need to update the model MultifieldCollectionModel
so that it implements Sling Model Exporter (e.g., ComponentExporter
or ContainerExporter
) and explicitly expose the list of child items using a getter annotated with @JsonProperty
.
@Model(
adaptables = Resource.class,
defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL,
resourceType = "your/component/resourceType",
adapters = {MultifieldCollectionModel.class, ComponentExporter.class}
)
public class MultifieldCollectionModel implements ComponentExporter {
@Self
private Resource resource;
private List<MultifieldItem> items;
@PostConstruct
protected void init() {
items = new ArrayList<>();
Resource childRes = resource.getChild("testList");
if (childRes != null) {
childRes.getChildren().forEach(child -> {
items.add(child.adaptTo(MultifieldItem.class));
});
}
}
@JsonProperty("testList")
public List<MultifieldItem> getItems() {
return items;
}
@Override
public String getExportedType() {
return resource.getResourceType();
}
}
MultifieldItem
Model@Model(adaptables = Resource.class
public class MultifieldItem {
@ValueMapValue
private String itemTitle;
@ValueMapValue
private String itemDesc;
public String getItemTitle() {
return itemTitle;
}
public String getItemDesc() {
return itemDesc;
}
}
<sly data-sly-use.model="com.example.MultifieldCollectionModel"
data-sly-list.item="${model.testList}">
<div>
<h3>${item.itemTitle}</h3>
<p>${item.itemDesc}</p>
</div>
</sly>
{
":type": "your/component/resourceType",
"testList": [
{
"itemTitle": "Title 1",
"itemDesc": "Description 1"
},
{
"itemTitle": "Title 2",
"itemDesc": "Description 2"
}
]
}
Views
Replies
Total Likes
Hi @NageshRaja ,
Try below solution:
1. Multifield Item Model
package com.project.core.models;
import org.apache.sling.models.annotations.Model;
import org.apache.sling.models.annotations.DefaultInjectionStrategy;
import org.apache.sling.models.annotations.injectorspecific.ValueMapValue;
import javax.inject.Inject;
@Model(adaptables = org.apache.sling.api.resource.Resource.class,
defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL)
public class MultifieldItem {
@ValueMapValue
private String itemTitle;
@ValueMapValue
private String itemDesc;
public String getItemTitle() {
return itemTitle;
}
public String getItemDesc() {
return itemDesc;
}
}
2. Component Model Exporter Class
package com.project.core.models;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.models.annotations.Model;
import org.apache.sling.models.annotations.DefaultInjectionStrategy;
import org.apache.sling.models.annotations.injectorspecific.Self;
import org.apache.sling.models.annotations.Exporter;
import org.apache.sling.models.annotations.injectorspecific.ValueMapValue;
import org.apache.sling.models.annotations.Default;
import org.apache.sling.models.annotations.injectorspecific.ChildResource;
import org.apache.sling.models.factory.ModelFactory;
import javax.annotation.PostConstruct;
import javax.inject.Inject;
import java.util.ArrayList;
import java.util.List;
import com.adobe.cq.export.json.ComponentExporter;
@Model(adaptables = Resource.class,
adapters = { ComponentExporter.class },
resourceType = "project/components/component-a",
defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL)
@Exporter(name = "jackson", extensions = "model.json")
public class ComponentAModel implements ComponentExporter {
@Self
private Resource resource;
@Inject
@Default(values = "")
private String test;
@Inject
@Default(values = "")
private String test1;
@Inject
@Default(values = "")
private String test2;
@Inject
@Default(values = "")
private String test3;
@ChildResource(name = "testList")
private List<Resource> testListResources;
@Inject
private ModelFactory modelFactory;
private List<MultifieldItem> testList;
@PostConstruct
protected void init() {
testList = new ArrayList<>();
if (testListResources != null) {
for (Resource res : testListResources) {
MultifieldItem item = modelFactory.createModel(res, MultifieldItem.class);
if (item != null) {
testList.add(item);
}
}
}
}
@JsonProperty("test")
public String getTest() {
return test;
}
@JsonProperty("test1")
public String getTest1() {
return test1;
}
@JsonProperty("test2")
public String getTest2() {
return test2;
}
@JsonProperty("test3")
public String getTest3() {
return test3;
}
@JsonProperty("testList")
public List<MultifieldItem> getTestList() {
return testList;
}
@Override
public String getExportedType() {
return resource.getResourceType();
}
}
3. HTL
<sly data-sly-use.model="com.project.core.models.ComponentAModel"
data-sly-list.item="${model.testList}">
<div class="multi-item">
<h3>${item.itemTitle}</h3>
<p>${item.itemDesc}</p>
</div>
</sly>
Deployment Notes
Multifield Path Structure in CRXDE:
- Author dialog must store multifield items under testList/ node.
- Each item should have itemTitle, itemDesc as properties.
- Example structure in /content:
component-a
└── testList
├── item0
│ ├── itemTitle = "Title 1"
│ └── itemDesc = "Description 1"
└── item1
├── itemTitle = "Title 2"
└── itemDesc = "Description 2"
Views
Replies
Total Likes
Views
Likes
Replies
Views
Likes
Replies
Views
Like
Replies
Views
Likes
Replies