Ready for action? If unsure, you should have a look at the first part of Fusion in Action and the Hitchhiker's Guide Part 1 and 2 before solving these exercises.
The demo node structure
For all the examples below, we assume the following nodes in the content repository:
The current context
An expression in Fusion has access to the context, which stores values about the current node, the current document node (the page) and the site node. The following variable names are available by default:
- node The current node, this could be the document node on the outer level or a content node when rendering nodes in a ContentCollection
- documentNode The current document node is the node that is used to render the current page
- site The site node is the root of your site
It's a wrap
Using FlowQuery means to wrap a value with the q function. This enables the use of all kinds of operations on the resulting FlowQuery object. Some operations will return another FlowQuery object that wraps a modified list of values and some operations will end up in a string or array value. These are called final operations.
Every non-final operation will return another FlowQuery object. The FlowQuery object always wraps a list of values and all operations work on these values.
${q(node).operation().anotherOperation()}
Getting node properties
Properties of nodes make up the actual content. For a node type all properties are automatically declared as variables for a Fluid template. But it's also useful to access properties explicitly to render different parts of a page.
If a FlowQuery result contains more than one node the property
operation will only return the property value of the first node.
Context
1. Write a FlowQuery expression to render the title
property of the current node as the title tag
On the document level the context variables node
and documentNode
refer to the same node instance. But when rendering content the variable node
will change to the current node - like a headline or text element. This is a convention used throughout the Neos rendering to always have a reference to the current node.
Traversing nodes
One of the main benefits of FlowQuery is an easy way to traverse nodes in the content repository. That means navigating and querying through the structure to find content. As the nodes are arranged in a tree, every node has a parent and zero or more children.
Context
2. Output the parent node and the current node title
property as the title tag
The node name is a way to reference nodes by name. This name might not be stable, as it is editable for document nodes by default. But automatically created child nodes like a ContentCollection are safe to reference by name. Most of the operations accept an optional filter argument that will narrow down the matched results. The children
operation is one of these operations and can be used to select only specific child nodes.
In it's simplest form the filter will just take a node name:
${q(node).children('nodeName')}
Context
3. Get the number of child nodes in the main
ContentCollection
Filtering attributes
But it's also possible to filter by the properties of a node. The syntax is based on CSS selectors for attributes and attribute values:
// Filter by property existence
${q(node).children('[title]')}
// Filter by property value
${q(node).children('[title="Hello world!"]')}
Context
4. Get the text
property value of the first child node having a text
property in the main
ContentCollection
Filtering node types
Besides their structure and properties, nodes also have a type. This is quite natural when thinking about content and in Neos CMS many scenarios can be modeled by using distinct node types.
When rendering content it is often necessary to only select nodes of a certain kind. The FlowQuery filter instanceof
will only match nodes that have a particular node type:
${q(node).children('[instanceof My.Package:NodeType]')}
Context
5. Find the first node of type TYPO3.Neos.NodeTypes:Text
in the main
ContentCollection and output the text property
As node types can have super types that will be extended to compose new types, the instanceof
operation will also match super types of a node. Thus, it is possible to filter nodes that have a specific node type either directly or as the parent type. In Neos the most prominent super types are TYPO3.Neos:Content
and TYPO3.Neos:Document
that make the distinction between nodes that are merely content elements or nodes that make up documents accessible via a URL.
Context
6. Get the count of all document child nodes of the current node ("Home")
For the rendering of a content node type it's sometimes necessary to find a parent node (or, more correctly, an ancestor) of a specific type or with a particular property. The closest
operation comes in handy to find the closest ancestor that matches a given filter.
Context
7. Find the closest ContentCollection (TYPO3.Neos:ContentCollection
) and output the node path of the current node, which will not be a document
The node path or node name can be accessed through the virtual properties _path
or _name
. They can be handy to debug the result of a FlowQuery.
Modifying the result
For a teaser or a list of some specific nodes it's often desirable to render each element in some way. In Part 2 of the Hitchhiker's Guide you already learned about the Collection Fusion object. The collection
property accepts anything that resembles a list of values, which is true for a FlowQuery result.
Besides just passing the result of a FlowQuery as the collection, it's possible to add specific elements to the result using the add
operation.
${q(node).add(q(node).children())}
Context
8. Render a list of nodes for a breadcrumb using a Collection object, the collection should contain the current node and all parents
Wrap up
Congratulation! If you made it this far and solved all code exercises you'll have a good overview of FlowQuery. It's a key piece to bring your content to life and knowing about the operations and filters will give you a great amount of flexibility.
FlowQuery Fu
Rewarded for solving code exercises in Fusion that involve FlowQuery. Proves sufficient knowledge to traverse nodes, find nodes of a certain type and access properties of nodes.
Update (March, 2018): Renamed TypoScript 2 to Fusion