Table of contents for child pages

Hi everyone,
I’m a bit stuck.

On a parent page I’d like to show a table of contents for its child pages and their headings (H1 + H2).

I got a version working, but the order doesn’t match what I configured under ?viewer=children&view=pinnedChildPages.

Is there a way to build a TOC that follows the same ordering as in the navigation sidebar?

The tree macros look odd for this use case; I’d prefer a plain text list.

Here’s my current TOC:

{{velocity}}
#set ($children = [])
#foreach ($childRef in $doc.getChildren())
  #set ($discard = $children.add($xwiki.getDocument($childRef)))
#end

#foreach ($childDoc in $children)
  == [[${childDoc.plainTitle}>>${childDoc.prefixedFullName}]]
  {{toc reference="${childDoc.prefixedFullName}" start="1"/}}
#end
{{/velocity}}

I also tried sorting by name like this:

{{velocity}}
#set ($children = [])
#foreach ($childRef in $doc.getChildren())
  #set ($discard = $children.add($xwiki.getDocument($childRef)))
#end

#set ($sorted = $sorttool.sort($children, 'plainTitle'))

#foreach ($childDoc in $sorted)
  == [[${childDoc.plainTitle}>>${childDoc.prefixedFullName}]]
  {{toc reference="${childDoc.prefixedFullName}" start="1"/}}
#end
{{/velocity}}

Thanks in advance!

This order is complex as it follows a configuration (see the Navigation config in the Admin UI), including Pinned Pages. So you’ll need to also follow it in your code.

Note that this is only direct children, and if there are a lot (like a few hundreds of thousands ;)), it won’t scale very well.

Also there’s no specific order, as you’ve noticed.

If you want to sort the best is to sort using a XWQL query.

Right now getchildren() does:

            Query query = getStore().getQueryManager()
                .createQuery("select distinct doc.fullName from XWikiDocument doc where "
                    + "doc.parent=:prefixedFullName or doc.parent=:fullName or (doc.parent=:name and doc.space=:space)",
                    Query.XWQL);
            query.addFilter(Utils.getComponent(QueryFilter.class, "hidden"));
            query.bindValue("prefixedFullName",
                getDefaultEntityReferenceSerializer().serialize(getDocumentReference()));
            query.bindValue("fullName", LOCAL_REFERENCE_SERIALIZER.serialize(getDocumentReference()));
            query.bindValue("name", getDocumentReference().getName());
            query.bindValue("space",
                LOCAL_REFERENCE_SERIALIZER.serialize(getDocumentReference().getLastSpaceReference()));
            query.setLimit(nb).setOffset(start).setWiki(wikiReference.getName());

            List<String> queryResults = query.execute();

You’ll need to do the same using the $services.query.* script API, but sort based on the plain title. See https://extensions.xwiki.org/xwiki/bin/view/Extension/Query%20Module

If you want to sort on the real title, then it’s more complex, you’ll need to retrieve the title and perform a sort on that. It’s also a lot more costly.