Handlebars is a templating language. You write HTML and use special expressions wrapped in curly braces, like ``, to insert data or use a function.
This guide covers basic Handlebars syntax: lists, objects, outputting values, built-in helpers, and comments. No prior experience is required. If you have used XSLT templates before, you will recognize many of the ideas — only the syntax is different.
Once you are comfortable with the basics, see Guide-template-structure.md to learn how a template is put together, where its data comes from, and how to edit and test one.
Your data is built from two building blocks: lists and objects.
A list is an ordered collection of items. It is written with square brackets [ ]:
"Columns": ["column_1", "column_2", "column_3"]
An object is a collection of “key–value” pairs. It is written with curly braces { }. Each key has a value (“key”: “value”):
"column_1": {
"referenceName": "System.Id",
"name": "ID",
"width": 75,
"type": "Integer"
}
Lists and objects can be nested inside one another. A common structure is a list containing objects:
"Columns": [
{
"referenceName": "System.Id",
"name": "ID",
"width": 75,
"type": "Integer"
},
{
"referenceName": "System.WorkItemType",
"name": "Work Item Type",
"width": 75,
"type": "String"
}
]
Why this matters: Looping and value lookups (below) are about walking through lists and reaching into objects. Recognizing the two shapes makes the rest of Handlebars easier.
To output a value, wrap its name in double curly braces:
Names that contain dots — for example System.Title — need to be wrapped in square brackets:
Some values are formatted with HTML. Double braces would print the raw HTML tags as regular text. Use triple braces to render the HTML correctly:
Helpers are functions used inside a template. A few are built in and always available, but you can also write your own — see Guide-custom-helpers.md.
If a value’s name is unknown (e.g. it comes from a variable), the lookup helper can be used to fetch the value using a name stored in another value.
Example: when looping over Columns, each column carries a referenceName and you want the field value that matches it.
Here
referenceNamecomes from the current column, andlookupuses it to find the matching value infields. The../steps up one level to reachfields, which exists outside theColumnslist — see Loops below.
Use #if to do something only when a value exists or is true. Add `` to provide a fallback:
Use #each to repeat a block once for every item in a list. Inside the loop, this refers to the current item:
Reaching outside the loop: Within a loop you are “inside” the current item. To reach something from the outer level, prefix it with ../:
Simplifying nested access When working inside a nested object, #with sets the context to that object so you can reference its keys directly, without repeating the prefix. Use ../ to step back out when you need something from the outer level:
To call a helper, write its name followed by its arguments. Helpers can be combined with the built-ins like #if. The example below uses a custom eq helper (covered in Guide-custom-helpers.md) to check whether two values are equal:
Use comments to explain your logic, leave notes, or temporarily disable a block. Comments never appear in the output: