Expand my Community achievements bar.

SOLVED

List Core Component exclude child pages based on a property

Avatar

Level 2

We are extending the List Core Component to display a list of child pages on the parent page.We have a requirement where our marketing partners can exclude some pages so that they are not eligible for being displayed in the list component. We are planning to have a checkbox in page properties. Only when this checkbox is checked for a child page, that child page will be eligible to be shown in list component.So basically only the pages that have this checkbox checked will be processed in the backend and then returned to UI if they meet other existing criteria. For eg, let's say there are 5 child pages under a parent page, but only 3 have this checkbox checked. Let's say a now user wants to see 4 child pages on the List Component, but he will only see the 3 that have this checkbox checked. 

 

How can we achieve this? There are methods populateChildListItems() and collectChildren(int startLevel, Page parent) which are populating the list of child pages and seems this check to exclude pages based on this property can be done there. But how can we "override" these private methods in our custom implementation?

1 Accepted Solution

Avatar

Correct answer by
Community Advisor

Hi @gautamg99016783 

 

In order to achieve required changes, you will have to implement the existing Adobe WCM list Model Interface in your own List model. Follow these steps:

  • If you look at the core component list.html file, it uses the Adobe List Model

 

<ul data-sly-list.item="${list.items}"
    data-sly-use.list="com.adobe.cq.wcm.core.components.models.List"
    data-sly-use.template="core/wcm/components/commons/v1/templates.html"
    data-sly-use.itemTemplate="item.html">
    <li data-sly-call="${itemTemplate.item @ list = list, item = item}"></li>
</ul>
<sly data-sly-call="${template.placeholder @ isEmpty=list.items.size == 0}"></sly>​

 

 

Here, com.adobe.cq.wcm.core.components.models.List is an Interface, you do not need to overlay this file as we will provide our own implementation of List.java interface

  •  In your code base, add dependency to core components in pom.xml

 

            <dependency>
                <artifactId>core.wcm.components.core</artifactId>
                <version>2.2.0</version>
                <groupId>com.adobe.cq</groupId>
                <scope>provided</scope>
            </dependency>
​

 

Make sure to change version as per your running AEM instance

  • Create your  new model Class which implements com.adobe.cq.wcm.core.components.models.List

 

import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.models.annotations.Model;

import com.adobe.cq.wcm.core.components.models.List;

@Model(adaptables = SlingHttpServletRequest.class, adapters = List.class,
resourceType = "my-project/components/content/my-list")

public class MyList implements List{
		
   //Give your own implementations of the methods

}​

 

The resourceType here must be the resourceType of your list component

  • We can not change/use/extend List implemetation of adobe as it is not exported by Core components bundle but since it is open source, we can create our own implementation. 
    https://github.com/adobe/aem-core-wcm-components/blob/master/bundles/core/src/main/java/com/adobe/cq... is the WCM core components internal implementation. You can copy everything and make changes. Make sure to use implementation as per core components version. This one is for v1.
  • Deploy and test if your own list implementaion is getting picked up.

Try out and let me know.

 

Thanks,

Nupur

View solution in original post

6 Replies

Avatar

Level 3

One way I can think of is that you can uncheck the read permissions for the group when the check option is clicked programmatically. This way you can ensure that only the pages with read permissions are returned.

Avatar

Correct answer by
Community Advisor

Hi @gautamg99016783 

 

In order to achieve required changes, you will have to implement the existing Adobe WCM list Model Interface in your own List model. Follow these steps:

  • If you look at the core component list.html file, it uses the Adobe List Model

 

<ul data-sly-list.item="${list.items}"
    data-sly-use.list="com.adobe.cq.wcm.core.components.models.List"
    data-sly-use.template="core/wcm/components/commons/v1/templates.html"
    data-sly-use.itemTemplate="item.html">
    <li data-sly-call="${itemTemplate.item @ list = list, item = item}"></li>
</ul>
<sly data-sly-call="${template.placeholder @ isEmpty=list.items.size == 0}"></sly>​

 

 

Here, com.adobe.cq.wcm.core.components.models.List is an Interface, you do not need to overlay this file as we will provide our own implementation of List.java interface

  •  In your code base, add dependency to core components in pom.xml

 

            <dependency>
                <artifactId>core.wcm.components.core</artifactId>
                <version>2.2.0</version>
                <groupId>com.adobe.cq</groupId>
                <scope>provided</scope>
            </dependency>
​

 

Make sure to change version as per your running AEM instance

  • Create your  new model Class which implements com.adobe.cq.wcm.core.components.models.List

 

import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.models.annotations.Model;

import com.adobe.cq.wcm.core.components.models.List;

@Model(adaptables = SlingHttpServletRequest.class, adapters = List.class,
resourceType = "my-project/components/content/my-list")

public class MyList implements List{
		
   //Give your own implementations of the methods

}​

 

The resourceType here must be the resourceType of your list component

  • We can not change/use/extend List implemetation of adobe as it is not exported by Core components bundle but since it is open source, we can create our own implementation. 
    https://github.com/adobe/aem-core-wcm-components/blob/master/bundles/core/src/main/java/com/adobe/cq... is the WCM core components internal implementation. You can copy everything and make changes. Make sure to use implementation as per core components version. This one is for v1.
  • Deploy and test if your own list implementaion is getting picked up.

Try out and let me know.

 

Thanks,

Nupur

Avatar

Level 2
Thanks Nupur. Yes I was trying the same approach, but was wondering if there is an alternative to copying the entire code. Seems not. I will continue with this and update. Thanks a lot!

Avatar

Level 2

The solution proposed would need adding a lot of overriden code. So we found this alternate way. This seems much cleaner.

 

We converted the OOTB maxItems field to a hidden field and set it to 0, which means ALL child pages will be read from the backend everytime since the value of this field is used ti fetch data. Then we added a new numberfield itemsToDisplay, which the authors will use to select the number of children to show in the List. This field behaves exactly like the maxItems would. So from an author's perspective nothing is changed.

 

Then in our Java code we will get all child pages and then use the value of itemsToDisplay to select the required number of items to display in the List.

 

Screen Shot 2020-06-16 at 5.54.11 PM.png

Avatar

Administrator
Really appreciate you sharing this with the community.


Kautuk Sahni

Avatar

Level 2

Our company had a similar scenario to this one.

We handled this as a new selection in the List Component dialog itself. (I was actually wanting to suggest this be included as an enhancement in the Adobe Core List Component. Would I ask about this as... a separate request?)

 

As an author, I can create a list of items matching my criteria (i.e., show me a list of all nodes below /parent tagged with <value>)

 

And, there is a separate path selector where I can determine items to exclude from that list even if they match my criteria. The List component includes a path selector and + allowing me to add nodes to my list that the list should ignore, even if they match.