Skip to content

Appendix E: Handlebars Usage in Formbird

This document is currently being updated

1 Purpose

Handlebars is a templating language which is compatible with and can be used within a Formbird template.

The pupose of this document is to provide:

  1. An overview of the Handlebars templating language (Section 2)
  2. A description of how the Handlebars templating language can be used within a Formbird template (Section 3).
  3. Examples of Handlebars usage within a Formbird template (Section 4).
  4. Links to resources and further reading on the Handlebars templating language (Section 5).

 

2 Handlebars Templating Language Overview

The basic unit of the Handlebars templating language is the Handlebars expression.

Handlebars expressions are wrapped in double curly braces i.e. {{ some expression }}.

Expressions tell Handlebars to look up and use the value of a field or to execute helper functions.

Helper functions allow you to execute simple logic, loop through arrays, manipulate data and more. Handlebars provides a number of built-in helpers such as the if conditional and the each iterator. You can also define your own helpers.

2.1 Basic Expressions

The simplest Handlebars expression is a field name wrapped in double curly braces which tells Handlebars to look up the field in the current context and use its value. When a Handlebars expression is written within a Formbird template, the current context will be the current Formbird document.

The Handlebars expression {{lastName}} means look up the lastName field in the current context and use its value. If the lastName field is not found then no value will be used.

Note:

When using Handlebars in a Formbird template, field names within a Handlebars expression should be prefixed with a value to indicate the current Formbird context of the field. For example, prefixing a field name with document. means look up the field name in the current Formbird document and use its value, whereas prefixing a field name with result. means look up the field name in the currently selected result returned by a Formbird filter query and use its value.

Hence, in Formbird, the Handlebars expression {{document.lastName}} means look up the lastName field in the current Formbird document and use its value.

A table of the valid prefixes to indicate a Formbird context can be found in Section 3

How it Works

graph TD
A("FORMBIRD TEMPLATE<br/>&quot;summaryNameRule&quot;: &quot;Contact - {{document.firstName}} {{document.lastName}}&quot;") -->|Handlebars<br/>Compiler| B("function()")
    C("CURRENT FORMBIRD DOCUMENT<br/>&quot;firstName&quot;: &quot;James&quot&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br/>&quot;lastName&quot;: &quot;McAllan&quot;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;") -->|"James<br/>McAllan"| B
    B-->|On execution|D("CURRENT FORMBIRD DOCUMENT<br/>&quot;summaryName&quot;: &quot;Contact - James McAllan&quot;<br/>&quot;firstName&quot;: &quot;James&quot;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br/>&quot;lastName&quot;: &quot;McAllan&quot;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;")

In the above diagram:

  1. A Formbird Template contains a "summaryNameRule" field whose value is defined as a concatenation of the text ''contact - '' and two Handlebars expressions separated by a space i.e.
    "summaryNameRule": "Contact - {{document.firstName}} {{document.lastName}}".

  2. The current Formbird document contains the fields
    "firstName": "James",
    "lastName": "McAllan"

  3. Handlebars takes the Handlebars expressions from the Formbird template and compiles them into a function.

  4. This function then executes, setting the values of Handlebars expression fields to the values of the corresponding fields in the current Formbird document.

  5. On execution of the function, the current Formbird document will have the "summaryName" field as shown below:

    "summaryName": "Contact - James McAllan".

2.2 Path Expressions

Handlebars expressions can also be dot-separated paths.

Example:

{{document.address.streetName}} means lookup the address field in the current Formbird document, then look up the streetName field in the result and use its value.

2.3 Block Expressions

In Handlebars, blocks are expressions that open with {{# }} and close with {{/ }}. Each of the Handlebars built-in helpers described in Section 2.4 below are examples of block expressions.

2.4 Built-In Helper Expressions

Handlebars provides a number of built-in helpers including the if, each, unless, and with block helpers. These built-in helpers provide the ability to execute simple logic.

Most built-in helpers are block expressions i.e. they open with {{# }} and close with {{/ }}. For example the if block helper opens with {{#if}} and closes with {{/if}}.

A Handlebars helper may be followed by parameters (separated by a space), as shown below:

{{#if parameter1 parameter2 ...}} Your content here {{/if}}

2.4.1 if Block Helper

The if block helper is used to conditionally execute a block expression. If the condition returns a truthy value, Handlebars will execute the if block. If the condition returns a falsy value, Handlebars will not execute the if block. The if block helper can also include an {{else}} section in order to define how to execute a falsy value.

Valid Falsy values in Handlebars are false, undefined, null, "", and [] where the latter two are the empty string and empty array.

Example 1:

A Formbird Template contains the Handlebars if block helper shown below:

{{#if document.countries}}Countries are present.{{else}}Countries are not present.{{/if}}

The current Formbird document contains the countries field shown below:

"countries": [
  "Australia",
  "New Zealand",
  "France"
]

On execution, the if block helper would evaluate the non-empty "countries" array as a truthy value and return the result:

Countries are present.

Example 2:

A Formbird Template contains the Handlebars if block helper shown below:

{{#if document.countries}}Countries are present.{{else}}Countries are not present.{{/if}}

The current Formbird document contains the countries field shown below:

"countries": []

On execution the if block helper would evaluate the empty "countries" array as a falsy value and return the result:

Countries are not present.

Example 3:

A Formbird Template contains the Handlebars if block helper shown below:

{{#if document.countries}}{{document.countries.[0]}}{{/if}}

The current Formbird document contains the countries field shown below:

"countries": [
  "Australia",
  "New Zealand",
  "France"
]

On execution the if block helper would evaluate the non-empty "countries" array as a truthy value and return the first value of the countries array, i.e. return:

Australia

2.4.2 unless Block Helper

The unlessblock helper is similar to the if block helper in that it is used to conditionally executes a block expression, except it operates on the falsy value i.e. the unless block helper is the inverse of the if block helper. If the condition returns a falsy value, Handlebars will execute the unless block. If the condition returns a truthy value, Handlebars will not execute the unless block. The unless block helper can also include an {{else}} section in order to define how to evaluate a truthy value.

Falsy values in Handlebars are false, undefined, null, "", and [] where the latter two are the empty string and empty array.

Example 1:

A Formbird Template contains the Handlebars unless block helper shown below:

{{#unless document.countries}}Countries are not present.{{else}}Countries are present.{{/unless}}

The current Formbird document contains the countries field shown below:

"countries": []

On execution, the unless block helper would evaluate the empty array as a falsy value and return the result:

Countries are not present.

Example 2:

A Formbird Template contains the Handlebars if block helper shown below:

{{#unless document.countries}}Countries are not present.{{else}}Countries are present.{{/unless}}

The current Formbird document contains the countries field shown below:

"countries": [
  "Australia",
  "New Zealand",
  "France"
]

On execution. the unless block helper would evaluate the non-empty array to a truthy value and return the result:

Countries are present.

2.4.3 each Block Helper

The each block helper is used to iterate over an array of items.

You can use {{this}} inside the each block to reference the value of the current array item being iterated over.

The following parameters can be used to provide additional information while iterating:

  • The {{@index}} parameter can be used inside the each block to access the current loop index. This index begins at 0 and increments by 1 with each iteration.
  • The {{@first}} parameter provides a boolean for implementing different logic for the first item when iterating over an array or a list of items.
  • The {{@last}} parameter provides a boolean for implementing different logic for the last item when iterating over an array or a list of items.
Example 1:

A Formbird Template contains the Handlebars each block helper shown below:

{{#each document.countries}}{{@index}}: {{this}};{{/each}}

The current Formbird document contains the countries field shown below:

"countries": [
  "Australia",
  "New Zealand",
  "France"
]

On execution, the each block helper would iterate over each value of the countriesarray and return the result:

0: Australia; 1: New Zealand; 2: France;
Example 2:

A Formbird Template contains a Handlebars each block helper shown below:

{{#each document.names}}
  {{#unless @last}}
    Name: {{document.firstName}} {{document.lastName}};
  {{else}}
    Name: {{document.firstName}} {{documemnt.lastName}}
  {{/unless}}
{{/each}}

The current Formbird document contains the names field shown below:

"names" : [
  {"firstName":"Mary","lastName":"McAllan"},
  {"firstName":"Reginald","lastName":"Katting"},
  {"firstName":"Emily","lastName":"Frousicker"},
  {"firstName":"Lily-Ann","lastName":"Arnott"}
]

On execution, the each block helper will iterate over each item of the names array and return the result:

Name: Mary McAllan; Name: Reginald Katting; Name: Emily Frousicker; Name: Lily-Ann Arnott

Note the unless block helper and the @last parameter were used to suffix each element of the array, except the last, with a semi-colon.

2.4.4 with Block Helper

The {{with}} block helper is similar to the if block helper in that it is used to conditionally executes a block expression , with one key difference.

Normally Handlebars first takes the Handlebars expressions from the Formbird template and compiles them into a function before evaluating the resulting function against the current Formbird document. Whereas the with block helper allows immediate access the current Formbird document.

If the condition returns a truthy value, Handlebars will immediately execute the with block. If the condition returns a falsy value, Handlebars will not execute the with block. The with block helper can also include an {{else}} section in order to define how to evaluate a falsy value.

Example:

A Formbird Template contains the Handlebars with block helper shown below:

{{#with document.author}}Written by {{document.firstName}} {{document.lastName}}{{else}}Unknown Author{{/with}}

The current Formbird document contains the author field shown below:

"author": {
    "firstName": "Lily-Ann",
    "lastName": "Arnott"
  }

The with block helper would immediately access the current Formbird document and return the result:

Written By Lily-Ann Arnott

 

3 Using Handlebars in Formbird

Often the best and simplest way of deliveriing a particular requirement is via a Handlebars expression written within a Formbird template. For example:

  1. As shown above, the basic Handlebars expression {{document.lastName}} is an instruction to look up and use the value of the lastName field in the context of the current Formbird document.
  2. The Handlebars built-in helpers described in Section 2.4 or Handlebars helpers defined by you can be used to incorporate logic within a Formbird template.

3.1 Use the value of a field in its current Formbird context

Generally the purpose of a Handlebars expression in a Formbird template is to look up and use the value of a field in its current Formbird context.

When using Handlebars in a Formbird template, field names within a Handlebars expression should be prefixed with a value to indicate the current Formbird context of the field, which can be:

  • A field in the context of the current Formbird document.
  • A field in the context of the current Formbird document template.
  • A field in the context of the current user's Formbird account document.
  • A field in the context of the current Formbird component definition.
  • A field in the context of the current selected result returned by a Formbird filter query.
  • The total count in the context of the current results returned by a Formbird filter query.
  • The array index in the context of the current selected result returned by a Formbird filter query.
  • The full set of results in the context of the current results returned by a Formbird filter query.

When used within a Formbird template, the Handlebars expression format for each of the above Formbird contexts is shown in the table below.

For each of the above Formbird contexts, the table below shows:

  1. The prefix to use to indicate the Formbird context.
Formbird Context Formbird Context Prefix Handlebars Expression Format Description Examples
Formbird document document. {{document.field name}} Look up and use the value of a field in the current Formbird document. {{document.lastName}}
Formbird document template tpl. {{tpl.field name}} Look up and use the value of a field in the template for the current Formbird document. {{tpl.documentId}}
Formbird component definition tplItem. {{tplItem.field name}} Look up and use the value of a field in the current Formbird component definition. {{tplItem.name}}
Formbird account document account. ((account.field name)) Look up and use the value of a field in the current user's Formbird account document. {{account.systemHeader.summaryName}}
Formbird filter query result result. {{result.field name}} Look up and use the value of a field in the currently selected result returned by a Formbird filter query. {{result.pipe_dia}}
{{result.systemHeader.summaryName}}
Formbird filter query result resultsCount {{resultsCount}} The total count of results returned by a Formbird filter query. {{resultsCount}}
Formbird filter query result resultsIndex {{resultsIndex}} The array index of the currently selected result returned by a Formbird filter query. {{resultsIndex}}
Formbird filter query result results {{results}} The full set of results returned by a Formbird filter query.
Example:

A sc-selected-asset component with a tooltip field defined as:

"tooltips": "Displaying Pipes of type {{document.filterPipes}} Pipe #{{resultsIndex}} of {{resultsCount}} size {{result.pipe_dia}} mm <a href='/form/{{result.documentId}}' target='_blank'>{{result.systemHeader.summaryName}}</a> Current User {{account.systemHeader.summaryName}} viewing {{tplItem.name}}"

would generate and display a tooltip field as shown below:

3.2 Using Handlebars in sc-datatables

See Section 3 Using Handlebars in Datatables of the sc-datatables component documentation.

3.2 Using Handlebars in sc-static-html

See Section 3 Using Handlebars in sc-static-html of the sc-static-html component documentation.

3.2 Using Handlebars in Mapping components

Handlebars functions can be used in sc-address-map, sc-street-address and sc-selected-asset
The setup is largely the same as with sc-datatables in terms of specifying functions (handlebarsHelpers), watching fields (updateWatchFields), passing parameters etc. The main exception is that any query only returns data necessary for the component (not the complete document) - 'additional' fields need to be specified by defining an 'additionalQueryFields' array.

"additionalQueryFields": [
    "type",
    "appTags",
    "systemType"
],

This is defined either in the layer (for that query), or at the root of the component (for the main query).
All filters and most of the formatting options accept handlebars functions. Refer to Appendix B: layers field documentation.

3.3 Client Script Overlay

Editing handlebars functions inline can be difficult once the function becomes more than a couple of lines long. To assist in editing handlebars functions you can use the Client Script Overlay template by appending /916d66b0-7dda-11ea-a1d9-53ac176796aa to your template. Use the dropdown to choose the field/function to edit the function. Note the function must exist on the template first, so it's recommended to set up the structure first and then edit using the overlay.

Example :

"handlebarsHelpers": [
        {
            "name": "myFunction",
            "function": "function(arg) { }"
        }
    ]

IMPORTANT: Do not edit the template using the template editor while editing using the Client Script Overlay (or vice versa) without first reloading the page to ensure the changes have been refreshed.

 

4 Examples

Example 1

Requirement

In this example, the Formbird document is required to:

  1. Have its summaryName field value set to the concatenation of "Property - " with the values of each of its street address fields i.e. its unitNo, streetNo, street, suburb and postcode fields.
  2. Handle street addresses that don't have a unitNo or a streetNo value so that the unitNo and " - " and streetNo are skipped.

Solution:

Define Formbird template to include the summaryNameRule field shown below:

"summaryNameRule": "Property - {{#with addressGeo.features.[0].properties}}{{#if unit_No}}{{unit_No}} - {{/if}}{{#if streetNo}}{{streetNo}} {{/if}}{{street}}, {{suburb}}, {{postcode}}{{/with}}"

Result

If the current Formbird Document contained the fields show below:

{
    "systemHeader": {
        "systemType": "document",
        "templateId": "cd02a730-6b11-11e9-98c0-e92fbfb6142f",
        "keyIds": [
         ],
        "createdDate": "2019-07-11T07:53:04.028Z",
        "createdBy": "65be85d0-66b8-11e7-b9f2-8fcf6a56c9da",
        "serverUpdatedDate": "2019-07-11T07:53:04.028Z",
        "serverCreatedDate": "2019-07-11T07:53:04.028Z",
        "versionId": "e99a35c0-a3b0-11e9-b25d-1d82576c71d1",
        "currentVersion": true,
    },
    "documentId": "e915ea92-a3b0-11e9-b25d-1d82576c71d1",
    "addressGeo": {
        "type": "FeatureCollection",
        "features": [
            {
                "type": "Feature",
                "properties": {
                    "type": "street",
                    "unit_No": "",
                    "streetNo": "600",
                    "street": "SNEYDES ROAD",
                    "suburb": "WERRIBEE",
                    "postcode": "3030",
                    "state": "VIC"
                },
                "geometry": {
                    "type": "Point",
                    "coordinates": [
                        144.68618641755836,
                        -37.897783153444955
                    ]
                }
            }
        ]
    },
    "status": "Active"
}

Then the with block helper would immediately access its street address fields and and include the summaryName field shown below in the current Formbird document:

"summaryName": "Property - 600 SNEYDES ROAD WERRIBEE, 3030"

 

5 Resources and Further Reading

Listed below are a few more resources and articles if you wish to dig deeper into the Handlebars templating language: