Handlebars - introduction
Publii uses Handlebars for theme creation. We have prepared a few predefined files which must be included in a basic theme. There are also a few additional files which can be added to a theme to achieve different layouts for a specific page like tags pages, authors pages, posts, pages, etc...
This article is an introduction to the most common Handlebars syntax elements which are necessary to create a theme in Publii.
How are Handlebars files rendered?
Handlebars are compiling *.hbs files and use context to render variables inside the template file.
A context is an object which contains data related to a current view.
It works in the following way:
*.hbs file + context = final output
For example, if the context is an object like:
{
"message": "Hello World!"
}
And the *.hbs file has the following structure:
<div>{{message}}</div>
Then, we will receive as an output the following code:
<div>Hello World!</div>
Code blocks and context
Context can be an object with nested values i.e.:
{
"message": {
"text1": "Lorem",
"text2": "Ipsum"
}
}
In this case, we have to ways to access the data in the object:
1) Access the specific field directly:
<div>{{message.text1}}</div>
2) Access the specific filed using code blocks:
{{#message}}
<div>{{text1}}</div>
{{/message}}
Code blocks are usually more useful as it creates a natural structure of the content in your *.hbs files. But sometimes you will need to access in the block a field which is one or more levels above the current level of nesting.
In this case, you have to use the ../ prefix. In the example, if we have the following context:
{
config: {
option1: "value1"
},
message: {
text1: "lorem"
}
}
If we will use the code blocks method to access the nested fields variables and we will need to access config.option1 field, we will have to use a following syntax:
{{#message}}
<div>{{text1}}</div>
<div>{{../config.option1}}</div>
{{/message}}
Conditional code blocks
Handlebars have two types of blocks - inline blocks and conditional blocks.
Conditional blocks can have two outputs depending on the condition - if it is true or false.
The simplest example of the conditional code block is the if block:
{{#if field}}
Text displayed if field in context is true
{{else}}
Text displayed if field in context is false
{{/if}
If you want to achieve a reversed behavior, you can use an unless conditional block:
{{#unless field}}
Text displayed if field in context is false
{{else}}
Text displayed if field in context is true
{{/unless}
Of course, you can use a lot of more conditionals blocks. The main thing to remember is a fact that you should open it with the {{#NAME CONDITION}}
syntax and close it with {{/NAME}}
fragment.
Loops
You can iterate arrays and objects with the #each helper.
So if you have an array of arrays for each person in the project, you can use the following syntax:
{{#each persons}}
{{name}} - {{email}}
{{/each}}
It can be used in the following context:
{
persons: [
{
name: "John",
email: "john@doe.com"
},
{
name: "Adam",
email: "adam@adam-and-eve.com"
}
]
}
The #each helper will generate a list of all persons in a list.
Comments
You can put comments inside your *.hbs files which won't be rendered in the final HTML output. The syntax for comments in Handlebars is very simple:
{{! Your comment here !}}
Custom elements
For Handlebars, you can define two custom elements:
- custom helpers,
- custom partials
Custom helpers can be used for simple operations and conditional blocks. They are usually used to do things that are impossible with available helpers.
You can use custom helpers for:
- Filtering content
- Add additional features (like blurred images for lazy-loading)
- Generate parametrized HTML output using a single line of code
Partials can be used for common parts of the themes. They are used to re-use the codebase. Thanks to partials, you can make changes to your theme in one place. That's why we highly recommend to use partials for reused theme parts - it will make theme maintenance much easier.
For example, Publii built-in themes partials can be used for:
- Page header,
- Page footer,
- Social sharing block,
- Pagination,
- Menu
Global variables
Some elements are common to all views and are used along with the normal context of the view.
It is called global variables - it is prefixed with an @ char. You can find a full list of these variables under global variables page.