Skip to main content
Level 2
Nov 12, 2024 10:57 AM UTC
Solved

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

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.
Tethich
TethichAccepted solution
Community Advisor
Nov 12, 2024 5:16 PM UTC

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

13 replies

arunpatidar
Community Advisor
Community Advisor
Nov 12, 2024 11:31 AM UTC
ZendarkkeAuthor
Level 2
Nov 12, 2024 12:22 PM UTC

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?

Translate
donquixote_dofl
Level 2
Nov 12, 2024 12:36 PM UTC

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.

Translate
donquixote_dofl
Level 2
Nov 12, 2024 12:44 PM UTC

If structure is like this

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

Translate
ZendarkkeAuthor
Level 2
Nov 14, 2024 11:56 AM UTC

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

Translate
Tethich
Community Advisor
TethichCommunity AdvisorAccepted solution
Community Advisor
Nov 12, 2024 5:16 PM UTC

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

Translate
ZendarkkeAuthor
Level 2
Nov 13, 2024 5:59 AM UTC

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?

Translate
arunpatidar
Community Advisor
Community Advisor
Nov 13, 2024 7:50 AM UTC

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.

Translate
Arun Patidar