# Expressions

Handlebars expressions are the basic unit of a Handlebars template. You can use them alone in a {{mustache}}, pass them to a Handlebars helper, or use them as values in hash arguments.

# Basic Usage

Handlebars expressions are some contents enclosed by double curly braces {{}}. In the below template, firstname is a variable that is enclosed by double curly braces, which is said to be an expression.

template
<p>{{firstname}} {{lastname}}</p>

If the below input object is applied to the template

input
{
  firstname: "Yehuda",
  lastname: "Katz",
}

Expressions are compiled to produce the output as follows:

output
<p>Yehuda Katz</p>

# Path expressions

Handlebars expressions can also be dot-separated paths.

template
{{person.firstname}} {{person.lastname}}

This expression looks up the person property in the input object and in turn looks up the firstname and lastname property within the person object.

Pass the below input object to the template

input
{
  person: {
    firstname: "Yehuda",
    lastname: "Katz",
  },
}

Output will be generated as below

output
Yehuda Katz

Handlebars also supports a deprecated / syntax, so you could write the above template as:

template
{{person/firstname}} {{person/lastname}}

# Changing the context

Some helpers like #with and #each allow you to dive into nested objects. When you include ../ segments in your path, Handlebars will change back into the parent context.

template
{{#each people}}
    {{../prefix}} {{firstname}} 
{{/each}}

Even though the name is printed while in the context of a comment, it can still go back to the main context (the root-object) to retrieve the prefix.

WARNING

The exact value that ../ will resolve to varies based on the helper that is calling the block. Using ../ is only necessary when context changes. Children of helpers such as {{#each}} would require the use of ../ while children of helpers such as {{#if}} do not.

{{permalink}}
{{#each comments}}
  {{../permalink}}

  {{#if title}}
    {{../permalink}}
  {{/if}}
{{/each}}

In this example all of the above reference the same prefix value even though they are located within different blocks. This behavior is new as of Handlebars 4; the release notes discuss the prior behavior as well as the migration plan. Handlebars also allows for name conflict resolution between helpers and data fields via a this reference:

# Literal segments

Identifiers may be any unicode character except for the following:

Whitespace ! " # % & ' ( ) * + , . / ; < = > @ [ \ ] ^ ` { | } ~

In addition, the words true, false, null and undefined are only allowed in the first part of a path expression.

To reference a property that is not a valid identifier, you can use segment-literal notation, [. You may not include a closing ] in a path-literal, but all other characters are allowed.

JavaScript-style strings, " and ', may also be used instead of [ pairs.

template
{{!-- wrong: {{array.0.item}} --}}
correct: array.[0].item: {{array.[0].item}}

{{!-- wrong: {{array.[0].item-class}} --}}
correct: array.[0].[item-class]: {{array.[0].[item-class]}}

{{!-- wrong: {{./true}}--}}
correct: ./[true]: {{./[true]}}

# HTML-escaping

In Handlebars, the values returned by the {{expression}} are HTML-escaped. Say, if the expression contains &, then the returned HTML-escaped output is generated as &amp;. If you don't want Handlebars to escape a value, use the "triple-stash", {{{:

In the below template, you can learn how to produce the HTML escaped and raw output.

template
raw: {{{specialChars}}}
html-escaped: {{specialChars}}

Pass the special characters to the template

input
{ specialChars: "& < > \" ' ` =" }

Expressions enclosed by "triple-stash" ({{{) produce the raw output. Otherwise, HTML-escaped output is generated as below.

output
raw: & < > " ' ` =
html-escaped: &amp; &lt; &gt; &quot; &#x27; &#x60; &#x3D;

# Helpers

Helpers can be used to implement functionality that is not part of the Handlebars language itself.

A helper can be registered at runtime via Handlebars.registerHelper, for example in order to uppercase all characters of a string.

preparationScript
Handlebars.registerHelper('loud', function (aString) {
    return aString.toUpperCase()
})

A Handlebars helper call is a simple identifier, followed by zero or more parameters (separated by a space). Each parameter is a Handlebars expression that is evaluated exactly the same way as described above in "Basic Usage":

template
{{firstname}} {{loud lastname}}

In this case, loud is the name of a helper, and lastname is a parameter to the helper. The template will uppercase the lastname property of the input:

input
{
  firstname: "Yehuda",
  lastname: "Katz",
}
output
Yehuda KATZ

# Prevent HTML-escaping of helper return values

When your helper returns an instance of Handlebars.Safestring the return-value is not escaped, even if the helper is called with {{ instead of {{{. You have to take care that all parameters are escaped properly using Handlebars.escapeExpression.

preparationScript
Handlebars.registerHelper("bold", function(text) {
  var result = "<b>" + Handlebars.escapeExpression(text) + "</b>";
  return new Handlebars.SafeString(result);
});

# Helpers with Multiple Parameters

Let us see another example of helpers with two parameters

template
{{link "See Website" url}}

In this case, Handlebars will pass the link helper two parameters: the String See Website and the value of people.url from the below provided input people object.

input
{ url: "https://yehudakatz.com/" }

The helper function link is used to generate a hyperlink as described in the script.

preparationScript
Handlebars.registerHelper("link", function(text, url) {
      var url = Handlebars.escapeExpression(url),
          text = Handlebars.escapeExpression(text)
          
     return new Handlebars.SafeString("<a href='" + url + "'>" + text +"</a>");
});

We will obtain the output using the input parameters

output
<a href='https://yehudakatz.com/'>See Website</a>

In the above example, You could use the exact same helper with dynamic text based on the value of people.text:

template
{{link people.text people.url}}
input
{
  people: {
    firstname: "Yehuda",
    lastname: "Katz",
    url: "https://yehudakatz.com/",
    text: "See Website",
  },
}

# Literal arguments

Helper calls may also have literal values passed to them either as parameter arguments or hash arguments. Supported literals include numbers, strings, true, false, null and undefined:

template
{{progress "Search" 10 false}}
{{progress "Upload" 90 true}}
{{progress "Finish" 100 false}}

# Helpers with Hash arguments

Handlebars provides additional metadata, such as Hash arguments, to helpers as a final parameter.

template
{{link "See Website" href=person.url class="person"}}

In that template,the final parameter href=people.url class="people" are hash arguments sent to the helper.

The keys in hash arguments must each be simple identifiers, and the values are Handlebars expressions. This means that values can be simple identifiers, paths, or Strings.

If we pass the below input to the template, the value of person.url can be obtained from the person object.

input
{
  person: {
    firstname: "Yehuda",
    lastname: "Katz",
    url: "https://yehudakatz.com/",
  },
}

As described in the helper script below, the hash arguments can be obtained from the last parameter options for further processing within the helper.

preparationScript
Handlebars.registerHelper("link", function(text, options) {
    var attributes = [];

    Object.keys(options.hash).forEach(key => {
        var escapedKey = Handlebars.escapeExpression(key);
        var escapedValue = Handlebars.escapeExpression(options.hash[key]);
        attributes.push(escapedKey + '="' + escapedValue + '"');
    })
    var escapedText = Handlebars.escapeExpression(text);
    
    var escapedOutput ="<a " + attributes.join(" ") + ">" + escapedText + "</a>";
    return new Handlebars.SafeString(escapedOutput);
});

The output of above helper is generated as below

output
<a class="person" href="https://yehudakatz.com/">See Website</a>

Handlebars also offers a mechanism for invoking a helper with a block of the template. Block helpers can then invoke that block zero or more times with any context it chooses.

Learn More: Block Helpers

# Disambiguating helpers calls and property lookup

If a helper is registered by the same name as a property of an input object, the helper has priority over the input property. If you want to resolve the input property instead, you can prefix its name with ./ or this. (or the deprecated this/)

template
helper: {{name}}
data: {{./name}} or {{this/name}} or {{this.name}}
input
{ name: "Yehuda" }
preparationScript
Handlebars.registerHelper('name', function () {
    return "Nils"
})

# Subexpressions

Handlebars offers support for subexpressions, which allows you to invoke multiple helpers within a single mustache, and pass in the results of inner helper invocations as arguments to outer helpers. Subexpressions are delimited by parentheses.

{{outer-helper (inner-helper 'abc') 'def'}}

In this case, inner-helper will get invoked with the string argument 'abc', and whatever the inner-helper function returns will get passed in as the first argument to outer-helper (and 'def' will get passed in as the second argument to outer-helper).

# Whitespace Control

Template whitespace may be omitted from either side of any mustache statement by adding a ~ character by the braces. When applied all whitespace on that side will be removed up to the first handlebars expression or non-whitespace character on that side.

{{#each nav ~}}
  <a href="{{url}}">
    {{~#if test}}
      {{~title}}
    {{~^~}}
      Empty
    {{~/if~}}
  </a>
{{~/each}}

with this context:

{
  nav: [{ url: "foo", test: true, title: "bar" }, { url: "bar" }];
}

results in output sans newlines and formatting whitespace:

<a href="foo">bar</a><a href="bar">Empty</a>

This expands the default behavior of stripping lines that are "standalone" helpers (only a block helper, comment, or partial and whitespace).

{{#each nav}}
  <a href="{{url}}">
    {{#if test}}
      {{title}}
    {{^}}
      Empty
    {{/if}}
  </a>
{{~/each}}

will render

<a href="foo">
  bar
</a>
<a href="bar">
  Empty
</a>

# Escaping Handlebars expressions

Handlebars content may be escaped in one of two ways, inline escapes or raw block helpers. Inline escapes created by prefixing a mustache block with \. Raw blocks are created using {{{{ mustache braces.

\{{escaped}}
{{{{raw}}}}
  {{escaped}}
{{{{/raw}}}}

Raw blocks operate in the same manner as other block helpers with the distinction of the child content is treated as a literal string.

Last Updated: 2/9/2023, 7:09:59 PM