Template syntax
This page provides side-by-side examples of the most common Fluid constructs
and their Handlebars counterparts. The examples assume a content element with
the variables
header,
bodytext,
items,
and
image.
Outputting a variable
Handlebars HTML-escapes every { expression by default.
Fluid:
{header}
Handlebars:
{{header}}
Raw / unescaped output
Use triple braces to output a value without HTML escaping. Reserve this for
content that has already been sanitized (e.g., a
parse-processed
RTE field).
Fluid:
{bodytext -> f:format.raw()}
Handlebars:
{{{bodytext}}}
Conditionals
{ is truthy: empty strings,
0, empty arrays, and
null are all falsy. For numeric comparisons, write a helper (see
Helpers).
Fluid:
<f:if condition="{header}">
<h1>{header}</h1>
</f:if>
<f:if condition="{showTeaser}">
<f:then><p>{teaser}</p></f:then>
<f:else><p>{fallback}</p></f:else>
</f:if>
Handlebars:
{{#if header}}
<h1>{{header}}</h1>
{{/if}}
{{#if showTeaser}}
<p>{{teaser}}</p>
{{else}}
<p>{{fallback}}</p>
{{/if}}
Use { as shorthand for a negated {
without an else branch:
Fluid:
<f:if condition="{hideDate}">
<f:else><time>…</time></f:else>
</f:if>
Handlebars:
{{#unless hideDate}}
<time>…</time>
{{/unless}}
Loops
Inside {, { refers to the current
item and @index holds the zero-based iteration counter.
@first and @last are boolean flags for the
boundary items.
Fluid:
<f:for each="{items}" as="item" iteration="loop">
<li class="{f:if(condition: loop.isFirst, then: 'is-first')}">
{item.title}
</li>
</f:for>
Handlebars:
{{#each items}}
<li{{#if @first}} class="is-first"{{/if}}>
{{this.title}}
</li>
{{/each}}
Nested { blocks access the parent scope via ../:
{{#each categories}}
<h2>{{this.title}}</h2>
{{#each this.items}}
<p>{{this.label}} (category: {{../title}})</p>
{{/each}}
{{/each}}
Scoping with {{#with}}
{ sets a new scope root, similar to assigning a sub-object
and then using it directly. Inside the block, properties of the given object are
accessible without a prefix.
Fluid (using a variable alias via f:alias):
<f:alias map="{addr: '{data.address}'}">
{addr.street}, {addr.city}
</f:alias>
Handlebars:
{{#with data.address}}
{{street}}, {{city}}
{{/with}}
Partials
Handlebars partials are resolved relative to the configured partial root paths
in the same way as templates. The partial name is the filename without the
.hbs extension.
Fluid:
<f:render partial="Teaser" />
<f:render partial="Card" arguments="{title: item.title, image: item.image}" />
Handlebars:
{{> Teaser}}
{{> Card title=item.title image=item.image}}
To pass the entire current context to the partial (as Fluid does with the
arguments=" attribute), just omit any arguments:
{{> Teaser}}
To pass a completely different context object, provide it as a positional argument before any hash arguments:
{{> Card item}}
Dynamic property access
Handlebars dot-path notation resolves nested public properties:
{. For getter resolution (using Extbase's
Object) and dynamic key lookups (where the key itself is a variable),
use the built-in
get helper:
Fluid:
{object.{dynamicKey}}
{object.privateProperty.arrayKey}
Handlebars:
{{get object dynamicKey}}
{{get object 'privateProperty[arrayKey]'}}
Comments
Handlebars comments are stripped from the rendered output and never appear in the HTML source. Use them for template-internal notes.
Fluid:
<!-- this comment appears in HTML source -->
Handlebars:
{{!-- this comment is stripped from the output --}}
Escaping Handlebars delimiters
To output a literal { in the rendered HTML, use the raw
block syntax:
{{{raw}}}}
This {{{will not be}}} parsed as Handlebars.
{{{{/raw}}}}