Sort nodes as they are ordered within the structure tree


I retrieve all TYPO3.Neos.NodeTypes:Headline content nodes of a document node using:

headings = ${q(documentNode).find('[instanceof TYPO3.Neos.NodeTypes:Headline]').get()}

I then render them using a f:for loop

<f:for each="{headings}" as="heading">

Both works. Only problem is that the nodes are not ordered as they are in the structure tree. How can I sort them by their structure tree position?

I’m using find() because the TYPO3.Neos.NodeTypes:Headline nodes are children of different ContentCollections. May this cause the wrong ordering?

You are right … find does not look at the hierarchy and ordering. If you need this you can do this.

headings = ${q(documentNode).children('[instanceof TYPO3.Neos:ContentCollection]').children('[instanceof TYPO3.Neos.NodeTypes:Headline]').get()}

This should give you all headlines that are direct children of content collections of your document.

Is it possible to make this code independent of the hierarchy of ContentCollections? The Headlines aren’t just direct children of the first level of ContentCollections in my document.

Not really … for nodes the cr basically stores the path and an ordering attribute (and lots more). That ways the ordering of the nodes works only relative to the parent-node. If you are using find to search a whole section the ordering becomes meaningless.

You can partly limit the effects by combining children and find like this:

 headings = ${q(documentNode).children('[instanceof TYPO3.Neos:ContentCollection]').find('[instanceof TYPO3.Neos.NodeTypes:Headline]').get()}

This will at least keep the order of the content collections. If you know your exact structure you can achieve a better ordering with more complex fusion:

You can define the rendering recursive if you really need the complete structure preserved:

# render all headlines below the current node ... traverse down recursively into collections to find headines inside
prototype(Vendor.Site:RecursiveHeadlineRenderer) < prototype( TYPO3.TypoScript:Value) {
  @context.node = ${this.node}
  node = null
  value = TYPO3.TypoScript:Case {
    isCollection {
      condition = ${q(node).is('[instanceof TYPO3.Neos:ContentCollection]')}
      renderer = TYPO3.TypoScript:Collection {
         collection = ${q(node).children('[instanceof TYPO3.Neos.NodeTypes:Headline]').get()}
         itemName = 'node'
         renderer = Vendor.Site:RecursiveHeadlineRenderer
    isHeadline {
       condition = ${q(node).is('[instanceof TYPO3.NodeTypes:Headline]')}
       renderer = Vendor.Site:HeadlineRenderer

#render a headline node
prototype(Vendor.Site:HeadlineRenderer) < prototype( TYPO3.TypoScript:Tag ) {
   content = ${q(node).property('title'}

# use like this 
headlines = Vendor.Site:RecursiveHeadlineRenderer {
    node = ${documentNode}

WARNIG: beware of untested code … has to be adjusted to your document structure anyways