Content nodes without content collections

or how to omit unnecessary content collections 

Neos 8.x

This page is for Neos 8.x and lower. The behavior changed in the new Event Sourced Content Repository in Neos 9.

Neos 9

This page is for Neos 9.0 with the new Event Sourced Content Repository.

Avoid unnecessary nesting

To represent structures in content, content collections can be used:

yaml
'Vendor.Site:Content.Team':
  childNodes:
    team:
      type: 'Neos.Neos:ContentCollection'
      constraints:
        nodeTypes:
          '*': false
          'Vendor.Site:Content.Team.Member': true

But adding a content collection as a child node, you end up with a Content Tree like this:

Neos node structure including a superfluous ContentCollection

Content structure with superfluous ContentCollection

The content collection is not needed when you know that there will always be only one collection of child nodes in the Team content node. 

Instead, the Team node can be defined as a content collection itself, allowing to add child nodes without additional nesting. 

It is still possible to define additional properties on the NodeType.

yaml
'Vendor.Site:Content.Team':
  superTypes:
    'Neos.Neos:ContentCollection': true
  constraints:
    nodeTypes:
      '*': false
      'Vendor.Site:Content.Team.Member': true
  properties:
    title:
       type: string

By deriving your NodeType from ContentCollection, the Content Tree will look like that:

Content structure without ContentCollection

To render the child nodes in a fusion template, use Neos.Neos.NodeCollection without indicating a NodePath:

fusion
prototype(Vendor.Site:Content.Team) < prototype(Neos.Neos:ContentComponent) {
    team = Neos.Neos:ContentCollection 
    renderer = afx`{props.team}`
}

A fixed content node in a document

Child nodes don't always have to be content collections, it is possible to define any node type as a child node. 

yaml
'Vendor.Site:Document.Page':
  childNodes:
    fixedTeaser:
      type: 'Vendor.Site:Content.Teaser'

To render the child node, use Neos.Neos:ContentCase and set the context value node to the fixed content node. 

fusion
prototype(Vendor.Site:Document.Page) < prototype(Neos.Neos:Page) { 
    body = Neos.Fusion:Component {
		fixedTeaser = Neos.Neos:ContentCase {
            @context.node = ${q(documentNode).children('fixedTeaser').get(0)}
        }														
		renderer = afx`{props.fixedTeaser}`
	}															
}

Written by