Get a grip on snippets with Handlebars

Avatar
OL Learn Design

If you’ve created OL Connect Designer templates for long documents like contracts and insurance policies before you’re undoubtedly familiar with snippets. A snippet is a small, ready-to-use piece of content that often contains one or more placeholders for data. Snippets can be stored in the template or fetched from a remote system like a Content Management System (CMS).

Snippet heavy templates can become hard to maintain when each snippet is accompanied by multiple scripts to apply personalization and conditions. There is a requirement for the snippets and scripts to be thoughtfully organized (grouping, naming conventions, search optimizations). But even then, things can become cluttered and may even impact the overall performance of your template. The Handlebars snippets in OL Connect Designer 2022.1 will vastly reduce the number of scripts for these documents and will help to keep templates lean by creating semantic snippets.

This article is an introduction to the Handlebars implementation in OL Connect Designer 2022.1 (this version is set for release by the end of May 2022). The article shows how to utilize Handlebars snippets by creating segments of a simplified insurance policy document.

About Handlebars

With having a background in web design one could be familiar with Handlebarsjs. It is a popular templating library that provides a simple way to merge HTML snippets with data. There are many online resources that provide you with valuable information.

A Handlebars snippet (also referred to as ‘template’) is essentially HTML mixed with special tags called expressions. Typically, these are placeholders for data fields, but these expressions can also apply simple logic using helpers such as if statements, each loops and more. As these tasks are driven/initiated from the snippet there is no need to create user scripts in the OL Connect template. Let’s have a closer look.

Note! This article focusses on using Handlebars snippets, which is the primary use case of this feature. It is good to understand that the implementation is not limited to snippets. How to use this feature with your sections and possible limitations will be covered in a separate article.

Expressions

A Handlebars expression is basically a variable wrapped with double curly braces, for example: {{contractNo}}. Below an example Handlebars snippet from an insurance policy document. The snippet uses a static HTML table to layout base information of the policy.

<table>
    <tbody>
        <tr>
            <td>Contract No.</td>
            <td>{{contractNo}}</td>
        </tr>
        <tr>
            <td>Participant</td>
            <td>{{contractHolder}}</td>
        </tr>
        …
    </tbody>
</table>

At first sight things are not very different from a standard OL Connect Designer snippet. Traditionally variables are wrapped in the @-sign or marked by HTML elements with an ID or class name. With Handlebars these concepts are replaced by expressions. The example shows two Handlebars expressions each referring to a field in the Data Model shown below.

Working with Handelbars snippets

In OL Connect Designer the Handlebars feature comes with its own snippet type (.hbs). Just like other snippet types these live in the Snippets folder located in the Resources panel of the template. Double click the entry to open the snippet editor.

Note! The editor for Handlebars snippets does not have a Design view. The reason for this is that the browser of the Design view does not understand some of the Handlebars expressions. It will try to correct the HTML structure, breaking your carefully crafted HTML code. Having said that, the Handlebars implementation is able to work with standard HTML snippets most of the time.

The editor comes with syntax highlighting for both HTML elements and Handlebars expressions. You can add expressions for data fields by typing their name wrapped with the double curly braces, or by using drag & drop from the Data Model view. The latter automatically wraps the field name with the double braces.

Utilizing the snippet

One of the goals of Connect’s Handlebars feature is to minimize the number of scripts in use. This simplifies creating and maintaining complex documents. However a script is still required to load the snippet and to prepare it for further processing. Following the Handlebarsjs documentation this process consists of three steps:

  1. Compile the snippet with Handlebars.compile() to a JavaScript function;
  2. Execute this function with data;
  3. Add the resulting personalized HTML to the document.

These steps can be executed from a standard OL Connect user script. The code below shows these steps in action. Where the current data record is passed in the function (this data is also referred to as the evaluation context).

let contractDetails = Handlebars.compile( 'snippets/contract-details.hbs' );
let contractDetailsHtml = contractDetails( record );
results.replaceWith( contractDetailsHtml );

Executing the JavaScript function with data returns the personalized HTML. In the example above the current data record is passed, this includes detail data and nested detail data when available. It is also possible to pass a detail table, detail table record or a custom JavaScript object directly.

Taking a shortcut

Instead of this three step approach one can use Handlebars.render( snippet, data ). This convenience method combines the compile and execution steps and renders the snippet. This makes our code easier to read. The data parameter is optional, when omitted the current record is passed automatically as the evaluation context.

// Explicitly passing the current record.
let contractHtml1 = Handlebars.render( 'snippets/contract.hbs', record );
results.replaceWith( contractHtml1 );
// The data (evaluation context) is omitted, the current record is passed.
let contractHtml2 = Handlebars.render( 'snippets/contract.hbs' );
results.replaceWith( contractHtml2 );
// Passing a specific detail table of the current record.
let clausesHtml = Handlebars.render( 'snippets/clauses.hbs', record.tables.clauses );
results.replaceWith( clausesHtml );
// Passing a custom object.
const person = {
  first: "Peter",
  last: "Parker"
}
let cardHtml = Handlebars.render( 'snippets/card.hbs', person );
results.after( cardHtml );

After the HTML is returned things are business as usual, standard OL Connect Designer scripting API commands, like after(), html(), replaceWith() etc, can be used to add the personalized content to the document.

Dynamically loading snippets

Let’s go back to the package policy example. Typically, the information for the policy in the package is stored in a detail table. By iterating over the records in the detail table one can populate a snippet for every detail record or compile a policy specific snippet. The latter assumes there is information in the detail record that can be used to define the path to the respective snippet.

The following user script iterates records in a detail table and passes the current detail record to the Handlebars snippet. This snippet is used for all policies (underwater it is cached).

let policies = record.tables.Policies
let htmlStr = ''

for( var i = 0; i < policies.length; i++ ){
    htmlStr += Handlebars.render( 'snippets/policy-details.hbs', policies[i] )
}

results.replaceWith( htmlStr )

The script concatenates the personalized HTML strings. The complete string is added to the document in one go using the replaceWith() function. This concatenating approach is a best practice to reduce the number of interactions with the section, which typically improves performance.

The following shows a similar loop, but in this case a snippet is dynamically compiled using the ref data field of the current detail record. The compiled snippets are cached so that they are not compiled repeatedly when a specific snippet is encountered more than once.

let policies = record.tables.Policies
let htmlStr = ''

for( var i = 0; i < policies.length; i++ ){
    let snippetPath = 'snippets/' + policies[i].fields.ref + '.hbs'
    htmlStr += Handlebars.render( snippetPath, policies[i] )
}

results.replaceWith( htmlStr )

Partials (or sub-snippets)

The policy snippets in our example contain common parts, examples are: the policy details, clauses and proxy/rep info. Instead of replicating these parts in every snippet one could store the respective HTML code in a separate Handlebars snippet. This can be injected in other Handlebars snippets using the partial call syntax. The following example loads multiple partials within a Handlebars snippet.

<h2>Bicycle</h2>

<!-- Loads the policy-details.hbs Handlebars snippet -->
{{> snippets/policy-details.hbs}}

<h3>Information about your bike</h3>
<table class="policy-table specifications">
...
</table>

{{> snippets/clauses.hbs}}
{{> snippets/representative.hbs}}

Note! The Handlebars documentation states that partials must be registered. In OL Connect this is not needed, one can call partials files directly.

Partials have access to data (evulation context) provided to the parent snippet.

Conditions

The Handlebars if helper conditionally renders a block of HTML. It can be compared to the Condition script wizard in the Designer, which is used to hide (or show) elements based on data value.

As block helpers are shown in the HTML code it becomes easier to identify conditional (or repeated) elements. The following example shows a conditional table row. It will not be rendered when the respective data property is empty, omitted or false.

<table>
    <thead>
        <th colspan=3>Special maximums</th>
    </thead>
    <tbody>
    {{#if jewelryVal}}
        <tr>
            <td>Jewelry</td>
            <td>€</td>
            <td>{{jewelryVal}}</td>
        </tr>
    {{/if}}
    ...
</table>

Subexpressions

Use subexpressions to perform logical/comparison operators. Connect’s Handlebars implementation supports helpers like: eq (equals), gt (greater than), gte (greater than or equals), lt (less than), lte (less than or equal), startsWith, endsWith, not and more. Some examples:

{{#if (eq membership 'gold')}}
	<p>Gold Members receive 80% Bonus Points on stays.</p>
{{/if}}
{{#if (not (eq membership 'silver') )}}
	<p>Not a Silver Member.</p>
{{/if}}
{{#if (startsWith productName 'OL Connect')}}
	<p>To be, or not to be, that is the question.</p>
{{/if}}

Loops

The Handlebars library also supports loops. The each block helper can be used to iterate over an array (this could be detail table) in order to repeat a block of HTML code for each entry. Inside the block simply refer to the data fields by name. The following example loops over the rows in the clauses detail table and inserts the values of the label and desc fields.

<ol>
{{#each clauses}}
	<li><strong>{{label}}<strong> {{desc}}</li>
{{/each}}
</ol>

Formatting data using OL Connect’s Formatter helpers

OL Connect adds various built-in data formatting helpers to the Handlebars implementation. These helpers are based on the Formatter object as found in the OL Connect Designer’s scripting API (upperCase, lowerCase, currency, currencyNoSymbol, grouped etc). The following shows how to apply common formatter helpers like: upperCase, currency:

<tr>
    <td>Name</td>
    <td>{{upperCase fullName}}</td>
</tr>
<tr>
    <td>Jewelry</td>
    <td>{{currency jewelryVal}}</td>
</tr>

Final thoughts

The Handlebars feature was introduced after researching templates of various customer projects (mainly policy documents). These templates shared the same characteristics: a Data Model with many data fields, a sheer amount of user scripts for personalization purposes, HTML fragments in the JavaScript code of the user scripts and one or more (often many) HTML snippets. This made these templates hard to maintain, especially when working on the same project with multiple users or revisiting a template after several months.

Recreating these templates using the Handlebars library showed a drastic reduction of user scripts. It resulted in semantic and easy to understand snippets. As content and logic are stored in the snippets, the business logic became easier to understand. For several templates the Handlebars variant showed a significant performance improvement. Documents were rendered faster without having to optimize user scripts (i.e. by creating scripts using ID and class selectors).

This article only scratches the surface of the Handlebars library but hopefully is a good reference to get started with Handlebars in your OL Connect Designer templates.

Tagged in: scripts, snippets



Leave a Reply

Your email address will not be published. Required fields are marked *

All comments (4)