A developer is creating a custom component on the page and needs to list all the child pages of the root page. How to do that and what is the correct way to do that?
Solved! Go to Solution.
Views
Replies
Total Likes
A good sample! except that it's better always to use try-with-resources as the resource resolver is of Closeable interface, and the ArrayList should be used instead of the default LinkedList only in limited cases when you need to update the list after filling it.
In addition from me, if you use those pages to build a list of links, you should check for other properties, for example, if the page is a redirect one, you should display the target page instead of found one, and also if you need to traverse no only first children, but a whole tree, I use this approach:
// public final class StreamUtils {
public static Stream<Page> descendants(@Nullable final Page rootPage) {
return Optional.ofNullable(rootPage).map(rootPage ->
Stream.concat(Stream.of(rootPage),
StreamSupport.stream(Spliterators.spliteratorUnknownSize(rootPage.listChildren(),
Spliterator.ORDERED), false)
.flatMap(StreamUtils::descendants)))
.orElse(Stream.empty());
}
I have inlined some utility functions that I use to get it shorter, I hope I didn't brake it as I did it right here not in IDE
final List<Page> allDescendantPages = StreamUtils.descendants(rootPage).collect(Collectors.toList());
Hi @nats ,
You can create a simple Sling Model class for your component to get the root page and access all the child pages of that root page.
Sample code for java model class :
package com.example.models;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ResourceResolverFactory;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.apache.sling.api.resource.Resource;
import com.day.cq.wcm.api.Page;
import com.day.cq.wcm.api.PageManager;
@Component(service = ChildPagesModel.class)
public class ChildPagesModel {
@Reference
private ResourceResolverFactory resourceResolverFactory;
private List<Page> childPages;
@PostConstruct
protected void init() {
childPages = new ArrayList<>();
String rootPagePath = "/content/your-site-root"; // Replace this with the actual path to your root page
ResourceResolver resourceResolver = null;
try {
// Get the ResourceResolver using ResourceResolverFactory
resourceResolver = resourceResolverFactory.getServiceResourceResolver(null);
PageManager pageManager = resourceResolver.adaptTo(PageManager.class);
if (pageManager != null) {
Page rootPage = pageManager.getPage(rootPagePath);
if (rootPage != null) {
Iterator<Page> childIterator = rootPage.listChildren();
while (childIterator.hasNext()) {
Page childPage = childIterator.next();
childPages.add(childPage);
}
}
}
} catch (Exception e) {
// Handle exceptions
e.printStackTrace();
} finally {
// Always close the ResourceResolver when done
if (resourceResolver != null) {
resourceResolver.close();
}
}
}
public List<Page> getChildPages() {
return childPages;
}
}
You can then use this model in your HTL code by doing
<div data-sly-use.childPages="com.example.models.ChildPagesModel"> <ul> <li data-sly-repeat.child="${childPages}"> <a href="${child.path}.html">${child.title}</a> </li> </ul> </div>
Hope it helps!
Thanks,
Ayush
A good sample! except that it's better always to use try-with-resources as the resource resolver is of Closeable interface, and the ArrayList should be used instead of the default LinkedList only in limited cases when you need to update the list after filling it.
In addition from me, if you use those pages to build a list of links, you should check for other properties, for example, if the page is a redirect one, you should display the target page instead of found one, and also if you need to traverse no only first children, but a whole tree, I use this approach:
// public final class StreamUtils {
public static Stream<Page> descendants(@Nullable final Page rootPage) {
return Optional.ofNullable(rootPage).map(rootPage ->
Stream.concat(Stream.of(rootPage),
StreamSupport.stream(Spliterators.spliteratorUnknownSize(rootPage.listChildren(),
Spliterator.ORDERED), false)
.flatMap(StreamUtils::descendants)))
.orElse(Stream.empty());
}
I have inlined some utility functions that I use to get it shorter, I hope I didn't brake it as I did it right here not in IDE
final List<Page> allDescendantPages = StreamUtils.descendants(rootPage).collect(Collectors.toList());
Views
Likes
Replies
Views
Like
Replies