Expand my Community achievements bar.

Applications for the 2024-2025 Adobe Experience Manager Champion Program are open!
SOLVED

Sling models adapt to great grand child nodes

Avatar

Level 9

Is it possible to adapt to great grand children using sling models. My content structure is as below which is created using nested multi-field.

comp-node/
  multi-field-node/
    item0/
         sub-multi-field-node/
            sub-item0/
            sub-item1/
    item1/
    item2/

As I understand with @ChildResource we can adapt grand-child of current resource.
I am looking for a way using annotations to adapt to great grand child nodes i.e sub-item0, sub-item1,..
thank you.

Topics

Topics help categorize Community content and increase your ability to discover relevant content.

1 Accepted Solution

Avatar

Correct answer by
Level 10

@Kamal_Kishor create one main component based and two bean sling models. Call first bean sling model using @childResource from main component model and similarly second bean model using @childresource from first bean model.

 

 

import org.apache.sling.api.SlingHttpServletRequest;
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.ChildResource;
import org.apache.sling.models.annotations.injectorspecific.ValueMapValue;

import javax.inject.Named;
import java.util.List;

@Model(
        adaptables = {Resource.class, SlingHttpServletRequest.class},
        defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL)
public class CustomImpl {

    @Named("multi-field-node")
    @ChildResource
    public List<Child> child;

    public List<Child> getChild() {
        return child;
    }


    @Model(adaptables = {
            SlingHttpServletRequest.class,
            Resource.class },
            defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL)
    public class Child {

        @Named("sub-multi-field-node")
        @ChildResource
        public List<GrandChild> grandChild;

        public List<GrandChild> getGrandChild() {
            return grandChild;
        }
    }

    @Model(adaptables = {
            SlingHttpServletRequest.class,
            Resource.class },
            defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL)
    public class GrandChild {

        @ValueMapValue
        public String grandChildField;

        public String getGrandChildField() {
            return grandChildField;
        }
    }

}

 

View solution in original post

5 Replies

Avatar

Correct answer by
Level 10

@Kamal_Kishor create one main component based and two bean sling models. Call first bean sling model using @childResource from main component model and similarly second bean model using @childresource from first bean model.

 

 

import org.apache.sling.api.SlingHttpServletRequest;
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.ChildResource;
import org.apache.sling.models.annotations.injectorspecific.ValueMapValue;

import javax.inject.Named;
import java.util.List;

@Model(
        adaptables = {Resource.class, SlingHttpServletRequest.class},
        defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL)
public class CustomImpl {

    @Named("multi-field-node")
    @ChildResource
    public List<Child> child;

    public List<Child> getChild() {
        return child;
    }


    @Model(adaptables = {
            SlingHttpServletRequest.class,
            Resource.class },
            defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL)
    public class Child {

        @Named("sub-multi-field-node")
        @ChildResource
        public List<GrandChild> grandChild;

        public List<GrandChild> getGrandChild() {
            return grandChild;
        }
    }

    @Model(adaptables = {
            SlingHttpServletRequest.class,
            Resource.class },
            defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL)
    public class GrandChild {

        @ValueMapValue
        public String grandChildField;

        public String getGrandChildField() {
            return grandChildField;
        }
    }

}

 

Avatar

Level 9

thanks @Imran__Khan 
I was checking if there was a direct annotation to do so but it seems it isn;t.

Avatar

Community Advisor

Can you try like this - Write a Sling Model At each parent level
-- For Node - comp-node and child resource node - multi-field-node
@Model(adaptables = Resource.class)
public class CompNodeModel {

@ChildResource
private MultiFieldNodeModel multiFieldNode;
//-- 
--//
}

 

----

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

@inject
private List<ItemModel> items;
/*
*/
}

----

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

@ChildResource
private SubMultiFieldNodeModel subMultiFieldNode;
/*
*/
}

 

 

====

 

CompNodeModel compNodeModel = resource.adaptTo(CompNodeModel.class);
List<SubItemModel> subItems = compNodeModel.getMultiFieldNode().getItems().get(0).getSubMultiFieldNode().getSubItems();

Avatar

Community Advisor

Hi @Kamal_Kishor 
There is no grandchildren annotation, if there is one, it would be very expensive in terms of performance to retrive a grand children node from many nodes.

 

You can go ahead with the suggestion by @Imran__Khan  and @SureshDhulipudi 

 

however you can create your own annotations also.



Arun Patidar

Avatar

Administrator

@Kamal_Kishor Did you find the suggestion helpful? Please let us know if more information is required. Otherwise, please mark the answer as correct for posterity. If you have found out solution yourself, please share it with the community.



Kautuk Sahni