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}
Copied!

Handlebars:

{{header}}
Copied!

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 parseFunc-processed RTE field).

Fluid:

{bodytext -> f:format.raw()}
Copied!

Handlebars:

{{{bodytext}}}
Copied!

Conditionals 

{{#if}} 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>
Copied!

Handlebars:

{{#if header}}
    <h1>{{header}}</h1>
{{/if}}

{{#if showTeaser}}
    <p>{{teaser}}</p>
{{else}}
    <p>{{fallback}}</p>
{{/if}}
Copied!

Use {{#unless}} as shorthand for a negated {{#if}} without an else branch:

Fluid:

<f:if condition="{hideDate}">
    <f:else><time></time></f:else>
</f:if>
Copied!

Handlebars:

{{#unless hideDate}}
    <time></time>
{{/unless}}
Copied!

Loops 

Inside {{#each}}, {{this}} 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>
Copied!

Handlebars:

{{#each items}}
    <li{{#if @first}} class="is-first"{{/if}}>
        {{this.title}}
    </li>
{{/each}}
Copied!

Nested {{#each}} blocks access the parent scope via ../:

{{#each categories}}
    <h2>{{this.title}}</h2>
    {{#each this.items}}
        <p>{{this.label}} (category: {{../title}})</p>
    {{/each}}
{{/each}}
Copied!

Scoping with {{#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>
Copied!

Handlebars:

{{#with data.address}}
    {{street}}, {{city}}
{{/with}}
Copied!

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}" />
Copied!

Handlebars:

{{> Teaser}}

{{> Card title=item.title image=item.image}}
Copied!

To pass the entire current context to the partial (as Fluid does with the arguments="{_all}" attribute), just omit any arguments:

{{> Teaser}}
Copied!

To pass a completely different context object, provide it as a positional argument before any hash arguments:

{{> Card item}}
Copied!

Dynamic property access 

Handlebars dot-path notation resolves nested public properties: {{user.address.city}}. For getter resolution (using Extbase's ObjectAccess) and dynamic key lookups (where the key itself is a variable), use the built-in get helper:

Fluid:

{object.{dynamicKey}}
{object.privateProperty.arrayKey}
Copied!

Handlebars:

{{get object dynamicKey}}
{{get object 'privateProperty[arrayKey]'}}
Copied!

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 -->
Copied!

Handlebars:

{{!-- this comment is stripped from the output --}}
Copied!

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}}}}
Copied!