Handlebars templates support a number of functions that can aid in properly rendering your text. In this article, we'll cover some of the most common functions and how they can be used in Workiva.
Note: Although we list each function separately here, many Handlebars functions can be "stacked" or used within another function.
EACH
The EACH function is most commonly used, and is intended for, processing a JSON. The function loops through a JSON object or array; the syntax of the function utilizes an opening and closing block. Each element in the array is available for operation within the EACH loop block:
{{#each object }}
{{object element}}
{{/each}}
In the Render Text Template and Render File Template commands, the JSON object/array to be processed is specified in the JSON Variables section:
The name specified in the JSON Variables section of the command is used in the EACH opening block of the template. For a simple JSON array such as the following, every key (Priority & Owner in the below example) is available for processing within the EACH loop:
[
{
"Owner Name": "Abby Steere",
"Priority": "High"
},
{
"Owner Name": "Jeff Hickey",
"Priority": "High"
},
{
"Owner Name": "Ryan Niebruegge",
"Priority": "High"
},
{
"Owner Name": "Ryan Niebruegge",
"Priority": "Low"
},
{
"Owner Name": "Abby Steere",
"Priority": "Medium"
},
{
"Owner Name": "Jeff Hickey",
"Priority": "Medium"
},
{
"Owner Name": "Ryan Niebruegge",
"Priority": "Medium"
}
]
Example
Task Owner,Task Priority
{{#each object_items}}
{{Owner}},{{Priority}}
{{/each}}
Rendered result
The EACH function can also process more complex JSON objects including those with nested arrays.
Example JSON object (product list)
{
"products": [
{
"id": 1,
"title": "iPhone 14",
"price": 799,
"brand": "Apple",
"category": "smartphones",
"images": [
"/products/1/1.jpg",
"/products/1/2.jpg",
"/products/1/3.jpg",
"/products/1/4.jpg",
"/products/1/thumbnail.jpg"
]
},
{
"id": 2,
"title": "iPhone 15",
"price": 899,
"brand": "Apple",
"category": "smartphones",
"images": [
"/products/2/1.jpg",
"/products/2/2.jpg",
"/products/2/3.jpg",
"/products/2/thumbnail.jpg"
]
},
{
"id": 3,
"title": "S23 Ultra",
"price": 1249,
"brand": "Samsung",
"category": "smartphones",
"images": [
"/products/3/1.jpg"
]
},
{
"id": 4,
"title": "Pixel 8",
"price": 799,
"brand": "Google",
"category": "smartphones",
"images": [
"/products/4/1.jpg",
"/products/4/2.jpg",
"/products/4/thumbnail.jpg"
]
}
]
,"limit":100
,"total":4
,"hasmore":false
}
Example
In this template we are accessing an item in the root (total) as well as looping over an array (products) of items:
JSON Object has {{response.total}} items:
{{#each response.products}}
{{title}}
{{/each}}
Rendered result
UNLESS and @FIRST / @LAST
The UNLESS function is most commonly combined with the @FIRST or @LAST operators to control the final rendered output.
For example, when creating a comma-delimited list of the values being iterated, a comma is unnecessary after the last item in the list. By combining UNLESS and @LAST, a comma-separated list can easily be generated that does not end with a comma.
Example
{{#each response.products}}{{title}}{{#unless @last}},{{/unless}}{{/each}}
Rendered result using the Product List object
IF / ELSEIF / ELSE and EQUAL
The IF, ELSEIF, and ELSE functions allow logic to be added to the template to account for different scenarios. The use of IF does not require ELSEIF or ELSE to be used if functions are also combined with EQUAL operators.
The equal operator can be used to compare text or numeric values. When comparing text values, if either of the values is explicitly specified and not retrieved from a variable, it must be enclosed in double quotes.
Example
In this example, "brand" in the IF function is retrieved from the JSON variable. At execution, the variable is replaced with the value in the brand element of the object.
{{brand}},{{#if (equal brand "Apple")}}iOS{{else}}Android{{/if}}
Rendered result using the Product List object
@KEY / THIS / @INDEX
The @KEY and THIS functions are useful when interacting with JSON objects where the key name varies or may not be known.
The @INDEX function returns the position of the item being processed in an each operation.
Note: The @INDEX function is zero-based so the first item in the list has an index value of 0, the second an index of 1, and so on.
Example JSON body
This body is the response from the Get File Properties command of the Workiva connector:
{
"created": "2023-11-20T21:02:09.000Z",
"id": "91af3ec18c554d5a81fd4ec4edc3a897",
"metadata": {
"account": {},
"amount": {
"numberFormat": ",."
},
"entity": {}
},
"name": "Sample.csv",
"numRecords": 3,
"originalFileSize": 72,
"status": "IMPORTED",
"tableId": "d1463c30226445819b0dddf57226ccf7",
"tags": {
"WK-Chains-Source": "https://h.sandbox.wdesk.com/s/wdata/oc/app/workiva-chains/find/executor?chainId=95631\u0026chainExecutorId=4217258"
},
"updated": "2023-11-20T21:02:18.000Z",
"userId": "V0ZVc2VyHzU1OTQwMTMxODMzMTE4NzI",
"version": 1
}
Example
{{#each properties.tags}}
{{@key}},{{{this}}}
{{/each}}
Rendered result
Combining functions
All of the functions outlined in this article can be used in combination with one another. EACH functions can be nested within other EACH functions; UNLESS, IF, @KEY, THIS, or @INDEX functions can be used within an EACH function to conditionally control the rendered output.
Example
Multiple functions are combined in this template to create an HTML-formatted table:
- The EACH function is used to loop through the products.
- An @INDEX is used to retrieve the position of the product in the array.
- An IF function evaluates the brand of the product and conditionally formats the text.
- A nested EACH statement processes the images for each product
- An UNLESS statement adds a line break (<br>) after each image link (except the last in the list)
<table border=1>
<tr><th>Item ID</th><th>Product</th><th>Brand</th><th>Price</th><th>Images</th></tr>
{{#each response.products}}
<tr>
<td>{{@index}}</td>
<td>{{title}}</td>
<td {{#if (equal brand "Apple")}}style="color:black;"{{else}}style="color:red;"{{/if}}>{{brand}}</td>
<td>{{price}}</td>
<td>{{#each images}}{{this}}{{#unless @last}}<br>{{/unless}}{{/each}}</td>
</tr>
{{/each}}
</table>
Rendered result
The resulting table when viewed in a webpage or HTML compatible email is displayed below: