How to obtain list of child components models in parent component sling model? | Community
Skip to main content
Level 2
November 12, 2024
Solved

How to obtain list of child components models in parent component sling model?

  • November 12, 2024
  • 3 replies
  • 2044 views

I have a container component and multiple 'card' child components. In the sling model of the container component i want to obtain a list of card component sling models.

Container component

   -card1
   -card2
   -card3
I want a list of card models to accessible in container component model so that in HTL i can iterate the list and access data of each card. How do i go about achieving this?

This post is no longer active and is closed to new replies. Need help? Start a new post to ask your question.
Best answer by Tethich

Hi @zendarkke 

 

If your container resource structure does contain an intermediate node that would in turn contain the card1, card2, card3 and so on, then the solutions you already received describe how you can map the children.

 

But if it does not, which I believe is your case, then the only thing you can do (as far as I know) is to write a code in your @PostConstruct method, get all the children from the current resource (the container), take only those matching the resourceType of a card and put in a list on the model class.

Not the best, but here is an example:

 

 

import java.util.List; import java.util.Optional; import javax.annotation.PostConstruct; 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.Self; @Model(adaptables = { Resource.class }, defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL) public class ContainerComponentModel { @Self private Resource container; private List<Resource> cards; @PostConstruct private void init() { Optional.ofNullable(container) .map(Resource::getChildren) .ifPresent(children -> children.forEach(child -> { if (child.isResourceType("your_card_resource_type")) { cards.add(child); } })); } }

 

 

 

Or if you want to complicate things a little more, I found this example also: https://www.jeroendruwe.be/aem-children-sling-model-annotation

3 replies

arunpatidar
Community Advisor
Community Advisor
November 12, 2024
ZendarkkeAuthor
Level 2
November 12, 2024

Hey , went through the example , just to clarify by using @ChildResource annotation above a List<childModel> , we should we able to get the list of all child nodes of that type?

donquixote_dofl
Level 2
November 12, 2024

From my understanding the @ChildResource annotation will give the mentioned resource only under the parent resource.
Instead we can make a CardModel, then use getter for List<CardModel> in the Container model.

donquixote_dofl
Level 2
November 12, 2024

If structure is like this

+Container
  +Cards
      + Card1
      + Card2
then you can use 
@ChildResource(name = "Cards")
private List<Resource> cardsResources;

ZendarkkeAuthor
Level 2
November 14, 2024

This code snippet worked fine until i changed structure of my component
My container component is having a superType of accordion component so node content structure is 
+Container
 +card1
  +card2
model code snippet

@14766979 @ChildResource private List<ChildModel> children;

 However here it is failing to fetch child models when in container html write this code ${model.children} , it shows up as empty,any reason as to why this is failing

Tethich
Community Advisor
TethichCommunity AdvisorAccepted solution
Community Advisor
November 12, 2024

Hi @zendarkke 

 

If your container resource structure does contain an intermediate node that would in turn contain the card1, card2, card3 and so on, then the solutions you already received describe how you can map the children.

 

But if it does not, which I believe is your case, then the only thing you can do (as far as I know) is to write a code in your @PostConstruct method, get all the children from the current resource (the container), take only those matching the resourceType of a card and put in a list on the model class.

Not the best, but here is an example:

 

 

import java.util.List; import java.util.Optional; import javax.annotation.PostConstruct; 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.Self; @Model(adaptables = { Resource.class }, defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL) public class ContainerComponentModel { @Self private Resource container; private List<Resource> cards; @PostConstruct private void init() { Optional.ofNullable(container) .map(Resource::getChildren) .ifPresent(children -> children.forEach(child -> { if (child.isResourceType("your_card_resource_type")) { cards.add(child); } })); } }

 

 

 

Or if you want to complicate things a little more, I found this example also: https://www.jeroendruwe.be/aem-children-sling-model-annotation

ZendarkkeAuthor
Level 2
November 13, 2024

But how do i create the intermediary node? Do i create an intermediary in the container node structure itself so that when i add child nodes its added under the intermediary or should this be dynamic on addition of child nodes?

arunpatidar
Community Advisor
Community Advisor
November 13, 2024

Hi @zendarkke 
You don't need to create intermediary node. The code @tethich shared work on that content structure but you can adjust the code to read children content from immediate node as well.

 

Please check other code references. Also share the content node structure when you author for this container component so we will guide you better.

Arun Patidar