Knowledge Base

Introduction to Handlebars Concepts

Last Modified:
29 Nov 2024
User Level:
Power User

If you don't have experience with Handlebars in other products or frameworks, this article aims to walk you through some basic concepts to get you up to speed.

What is Handlebars exactly?

Handlebars in Terminalfour is implemented using handlebars.java which is a Java port of the popular templating engine handlebars.js. This open source templating engine is a standard used by many other frameworks and platforms so many developers are already familiar with how it works.

Glossary of Terminology

Helper

A helper is a function you can use in your template (e.g. Page Layout or Content Layout) to do some work, perform an action, or output a value. For example, different  helpers could do things like format dates, change text to uppercase, or even output the contents of Content Elements.

Terminalfour has shipped a large number of Helpers out of the box that you can use when making your Content and Page Layouts. You can learn more in our getting started guide.

Expression

An expression is anything inside the double curly braces {{...}}. It can be a variable, a helper, or a combination of both. Expressions are what Handlebars evaluates and replaces in the final HTML.

Block-level expression

A block-level expression is a type of expression that uses an opening and a closing tag (like HTML) to define a larger chunk of content. Block expressions are typically used to control how content inside the block is rendered, often based on conditions, loops, or custom logic.

Block-level expressions are opened with a # character and closed with a / character (see below for examples)

Common use cases

Conditionals

Only display a value when a condition is true:

{{#ifSet element="Title"}}
  <p>This is only output if the Title element is set</p>
{{/ifSet}}

Loops

Loop over an array and output data for each iteration:

{{#each (list element="Department")}}
  <p>Department name: {{name}}</p>
{{/each}}

Providing an area for accessing locally scoped variables

Some Handlebars expressions are variables that are only available inside a Block-level expression.

In the following example we'll use the link Helper as a block level expression and once we're inside that block we have access to the linkUrl and linkText variables.

{{#link element="Section Link"}}
  <p>{{linkUrl}} - This linkUrl variable is only available inside the link helper</p>
  <p>{{linkText}} - This linkText variable is only available inside the link helper</p>
{{/link}}

Subexpression

A subexpression is an expression inside another expression. It’s used when you want to call a helper or a calculation inside another expression. Subexpressions are wrapped in parentheses.

For example if we wanted to use the publish Helper to output the Title element of a Content item it might look like this:

{{publish element="Title"}}But if we wanted to make use of the built in upper Helper to output that value in uppercase we'd need to pass in the publish Helper into the upper Helper as a subexpression like this:

{{upper (publish element="Title")}}

"Double stashing" and "Triple stashing"

With some limited exceptions, Handlebars HTML-escapes values returned by an expression using two curly-braces (e.g. {{expression}}).

This means certain special characters will be converted to their HTML equivalents. For example, if a user entered a value of < then a "double-stashed" handlebars expression would convert that to &lt;.

If you don't want Handlebars to escape a value, use the "triple-stash", {{{

Double-stash example

{{publish element="Title"}}

If a user enters the value <h2>Test</h2> into a Title element then this expression would output

&lt;h2&gt;Test&lt;/h2&gt; (the value is HTML-escaped)

Triple-stash example

{{{publish element="Title"}}}

If a user enters the value <h2>Test</h2> into a Title element then this expression would output

<h2>Test</h2> (the value is not HTML-escaped)

Handling whitespace in Handlebars layouts

By default, whitespace that exists inside your layouts (for example inside block-level expressions) is retained once the Handlebars code is processed.

In almost all cases this won't be a problem because the additional whitespace is ignored by web browsers. If you do need full control of the whitespace of your published content you can tell handlebars to ignore the additional whitespace.

For example, if we had a layout that contained:

{{#link element="Section Link"}}
  {{linkUrl}}
  <br>
  {{linkText}}
{{/link}}

When this publishes if we were to look at the source code of the page the link URL, the <br> tag, and the link text will all be on separate lines with two space characters before them.

We can use the ~ character in our Handlebars expression to tell Handlebars to ignore the whitespace and output everything on a single line.

That may look like this:

{{#link element="Section Link" ~}}
  {{~linkUrl~}}
  <br>
  {{~linkText~}}
{{~/link}}

When the ~ is applied, all whitespace on that side of the expression will be removed up to the first handlebars expression or non-whitespace character on that side.

Adding Comments in Handlebars Layouts 

Handlebars allows you to add comments in your layouts that will be ignored when a page is being Previewed or Published.

This might be useful if you want to add some comments about how a layout works but don't want those comments to end up on the published site.

Handlebars comments begin with a {{!-- and end with --}}

For example:

{{!-- This is a comment and won't appear on the published page --}}

Comments can span multiple lines:

{{!--
  This is a
  multi-line comment.
--}}