Node Type Constraints
In a typical Neos project, you will create lots of custom node types. However, many node types should only be used in a specific context and not everywhere. Neos allows you to define node type constraints, which restrict the possible node types that can be added as children of a specific node type. There are two ways to do this:
Regular node type constraints are defined per node type. They apply in any context the node type appears in.
Additionally, when a node type has auto-created child nodes (see Node Type Definition), you can define additional constraints that only apply for these child nodes. This allows you to restrict node type usage depending on the context that the node types are placed in.
Note
Node type constraints are cached in the browser’s session storage.
During development, it’s a good idea to run sessionStorage.clear()
in the browser console to remove
the old configuration after you make changes. Alternatively, you can use an anonymous browser tab to
avoid storing outdated node type constraints.
Regular Node Type Constraints
Let’s assume that, inside the “Chapter” node type of the Neos Demo Site (which is a document node), one should only be able to create nested chapters, and not pages or shortcuts. Using node type constraints, this can be enforced:
'Neos.Demo:Chapter':
constraints:
nodeTypes:
'Neos.Neos:Document': false
'Neos.Demo:Chapter': true
In the above example, we disable all document node types using 'Neos.Neos:Document': false
, and then enable the
Neos.Demo:Chapter
node type as well as any node type that inherits from it. The reason why we use
'Neos.Neos:Document': false
instead of '*': false
here is that by default, only document node types are
allowed as children of other document node types anyway (see further down for more information regarding the defaults).
You might now wonder why it is still possible to create content inside the chapter (because everything except Chapter
is disabled with the above configuration): The reason is that node type constraints are only enforced for nodes which
are not auto-created. Because Neos.Demo:Chapter
has an auto-created main ContentCollection
, it is still possible
to add content inside. In the following example, we see the node type definition which is shipped with the demo website:
'Neos.Demo:Chapter':
superTypes:
'Neos.Neos:Document': true
childNodes:
'main':
type: 'Neos.Neos:ContentCollection'
The main
ContentCollection is still added, even though you cannot add any more because ContentCollections are not allowed
according to the node type constraints.
Auto-Created Child Node Constraints
Let’s assume that our chapter node type should only contain text within its main ContentCollection. This is possible using additional constraints for each auto-created child node. These constraints will only be applied for the configured auto-created child nodes - not for any others, even if they are of the same type.
'Neos.Demo:Chapter':
childNodes:
'main':
type: 'Neos.Neos:ContentCollection'
constraints:
nodeTypes:
'*': false
'Neos.NodeTypes:Text': true
Override Logic and Default Values
The following logic applies for node type constraints:
Constraints are only enforced for child nodes which are not auto-created.
You can specify node types explicitly or use ‘*’ to allow/deny all node types.
Setting the value to true is an explicit allow
Setting the value to false is an explicit deny
The default is to always deny (in case ‘*’ is not specified).
More specific constraints override less specific constraints. Specificity is deduced from the inheritance hierarchy of the node types. This means that e.g. setting ‘*’: false will only apply if no more specific constraint has been set, such as ‘Neos.Neos:Document’: true.
Node type constraints are inherited from parent node types. If your node type has listed Neos.Neos:Document as a superType, its constraints will apply for your node type as well.
The last rule is especially important, since most node types you define will have either Neos.NodeTypes:Page
(which, in turn, inherits from Neos.Neos:Document`) or ``Neos.Neos:Content
as superTypes. You should know which
constraints are defined per default in order to effectively override them. These are the current defaults for these
two node types - this is taken from NodeTypes.yaml
in the Neos.Neos package.
'Neos.Neos:Document':
constraints:
nodeTypes:
'*': false
'Neos.Neos:Document': true
The document node type, by default, allows any other document node type below it. This means that if you want to
disable all document node types under your custom one, setting '*': false
will have no effect on anything inheriting from
Neos.Neos:Document
- the more specific constraint 'Neos.Neos:Document': true
will override it. You will need to set
'Neos.Neos:Document': false
instead.
The default content node type, on the other hand, only has the catch-all constraint. If you want to enable any child nodes, you can simply allow them.
'Neos.Neos:Content':
constraints:
nodeTypes:
'*': false
Examples
You can use YAML references (with the &xyz
and *xyz
syntax) to re-use constraints. Here’s how to
disallow nested Two/Three/FourColumn inside a multi column element:
'Neos.NodeTypes:Column':
childNodes:
column0:
constraints: &columnConstraints
nodeTypes:
'Neos.NodeTypes:TwoColumn': false
'Neos.NodeTypes:ThreeColumn': false
'Neos.NodeTypes:FourColumn': false
column1:
constraints: *columnConstraints
column2:
constraints: *columnConstraints
column3:
constraints: *columnConstraints