There are many solutions on how to render custom document node types, the most common propagated are the “Additional root matcher condition and page path copy” or “Additional PrimaryContent condition” approaches for custom document node types. (I can elaborate on them if someone needs more explanation to follow this).
I’d like to propose a different solution that I think plays out much nicer for different scenarios and is more consistent with the way content node types are rendered in Neos by default.
Document prototypes
The default root matcher condition is adjusted to not render the path page
by default, but a prototype derived by the name of the current document node type:
root {
default {
type = ${q(node).property('_nodeType') + '.Document'}
renderPath >
}
}
The base page rendering is defined in a custom prototype, so it can be re-used easily:
prototype(MyProject.MySite:DefaultPage) < prototype(Page) {
body {
templatePath = 'resource://MyProject.MySite/Private/Templates/Page/Default.html'
}
// And many more adjustments to the Page
}
Note: This prototype should only contain the bare minimum, so no ContentCollections or other node type specific definitions should be placed here.
The actual rendering of document node types is defined like this:
prototype(TYPO3.Neos.NodeTypes:Page.Document) < prototype(MyProject.MySite:DefaultPage) {
body {
content {
main = PrimaryContent {
nodePath = 'main'
}
}
}
// E.g. do some other adjustments of the Page object
}
This already renders documents of the type TYPO3.Neos.NodeTypes:Page
correctly. But what about custom document node types?
For each custom document node type a prototype is defined that renders the document for that type:
prototype(MyProject.MySite:Product.Document) < prototype(MyProject.MySite:DefaultPage) {
body.content.main = MyProject.MySite:Product
}
This will use the auto-generated TS prototype for the MyProject.MySite:Product
node type to render the main content. All Page
properties can be freely adjusted (e.g. include additional JS / CSS, change classes).
The nice thing is, that the auto-generated prototype already contains all of the document node type properties as TS properties, so there’s no need to map every property individually (myProperty = ${q(node).property('myProperty')}
) for the rendering.
There’s a small caveat when using layouts (or formats) because they are not based on prototypes, but it works well by declaring the paths to render one of the document prototypes:
default = TYPO3.Neos.NodeTypes:Page.Document
landingPage = TYPO3.Neos.NodeTypes:Page.Document {
// Adjust some properties here
}