Handlebars: Partials, Helpers & much more
Handlebars: Partials, Helpers & much more

Handlebars: Partials, Helpers & much more

Spread the love
Handlebars: Partials, Helpers & much more
Source: Handlebars Official Website

Handlebars is templating language used for rendering dynamic data both for frontend as well as backend. Skeleton of HTML is fixed for everyone as hbs template and during run time dynamic data will create an end HTML file. Just by putting {{}}, you can use the same HTML template file multiple times. During the run time {{}} is replaced by actual data. It is one of the template engines used in Node.js. HTML files generated by Node.js are called “Server-side Rendered(SSR)”. It’s an extension of the Mustache template language, which is mostly focused on simplicity and minimal templating. In today’s post of “Handlebars: Partials, Helpers & much more“, we are going to discuss the following things.

  1. Partials
  2. Helpers
  3. Implementation of HBS in live project

We are going to use two files 1. index.hbs & 2. index.js file to show the example. I am going to show you some of the most popular in-built helpers.

Partials :

Partials in handlebars are some reusable templates, that can be accessed from any other templates. It must be registered via Handlebars.registerPartial.

Helpers:

Helpers in handlebars are function which will perform a certain action on given input & returns with the output. Some of the in-built helpers are #if, #unless, #each, #with, log & lookup.

#unless:

It is an inbuilt block helper, used to check conditional statements in handlebars. If the value is false the content inside the if block is rendered. It is the opposite of #if helper.

For eg:

// Code in index.js
{
  fruits: {
    "Apple": true,
    "Cucumber": false,
    "Banana": true,
  },
}
// Code in index.hbs
{{#unless fruits.Cucumber}}
  <li>Cucumber is not fruit</li>
{{/unless}}

#if:

It is an inbuilt block helper, used to check conditional statements in handlebars. If the value is true the content inside the if block is rendered. Unlike javascript code, it will not do a comparison like ≥ or ===. If you want to perform such an operation either preprocess the data before rendering or create a helper function.

For eg:

// Code in index.js
{
  fruits: {
    "Apple": true,
    "Cucumber": false,
    "Banana": true,
  },
}
// Code in index.hbs
{{#if fruits.Apple}}
  <li>Apple is fruit</li>
{{/if}}

#each:

Each is an inbuilt block helper, used in handlebars to render the array input. You can access the parent object by coming out of the array through this “../parentObject.property”. If the array contains an object, you can access the value by calling the key of the object

For eg:

// Code in index.js
{
  type: "Fruits List",
  fruits: [
    "Apple",
    "Mango",
    "Banana",
  ],
}, {
  type: "Books List",
  books: [{
    autherName: "John Doe",
    publishedOn: "1998",
    bookName: "Magics of life"
   }, {
    autherName: "Smith Carl",
    publishedOn: "2004",
    bookName: "Black hole: Begining"
   }],
}
// Code in index.hbs
<ul class="fruits">
  {{#each fruits}}
    <li>{{this}} is part of {{../type}}</li>
  {{/each}}
</ul><ul class="books">
  {{#each books}}
    <li>{{this.autherName}} published {{this.bookName}} on {{this.publishedOn}}</li>
  {{/each}}
</ul>

Custom Helpers:

You have to register the helper with handlebars in order to use it in the template. It takes two arguments: helper name & Function arguments

// Code in index.js
handlebars.registerHelper(‘calDiscountAmount’, (planValue, discountPer) => ((planValue * discountPer) / 100).toFixed(0))

// Code in index.hbs
<p>
Discount of Rs.{{calDiscountAmount 1000 20}}
</p>
// On execution it will show
Discount of Rs.200

Let’s see a complete demo of handlebars.

<!DOCTYPE html>
<html>
   <head>
   <title>{{title}}</title>
  {{> (whichPartial)}}
</head>
<body>
 {{>nav}}
 <section>
  {{#each products}}
  <div class="product">
   <img src="{{priductUrl}}" alt="{{productAltText}}" />
   <div class="description">
    <h3>{{productName}}</h3>
    <h5>${{productPrice}}</h5>
    {{#if discountPer}}
    <span>Discount of ${{calDiscountAmount productPrice      discountPer}}</span>
    {{#if}}
    {{#if isInInventory}}
    <h4>Qty: {{productQty}}</h4>
    {{else}}
    <h4>Out of stock</h4>
    {{/if}}
    </div>
   </div>
  {{/each}}
  </section>
 </body>
</html>

Content in index.js

const Handlebars = require('handlebars');
const nav = fs.readFileSync('./nav.hbs').toString();
const suppFilesProd = fs.readFileSync('./suppFilesProd.hbs').toString();
const suppFiles = fs.readFileSync('./suppFiles.hbs').toString();
const products = [{
 priductUrl: 'https://guesseu.scene7.com/is/image/1234',
 productAltText: 'Sneaker',
 productName: 'Gloria high logo sneaker',
 productPrice: 100,
 isInInventory: true,
 productQty: 200,
 discountPer: 20,
 }, {
 priductUrl: 'https://guesseu.scene7.com/is/image/4567',
 productAltText: 'Shirt',
 productName: 'Check print shirt',
 productPrice: 100,
 isInInventory: true,
 productQty: 20,
 discountPer: null,
 }, {
 priductUrl: 'https://guesseu.scene7.com/is/image/8756',
 productAltText: 'Bag',
 productName: 'Cate rigid bag',
 productPrice: 100,
 isInInventory: false,
 productQty: 35,
 discountPer: null,
}];

handlebars.registerHelper(‘calDiscountAmount’, (planValue, discountPer) => ((planValue * discountPer) / 100).toFixed(0));
handlebars.registerHelper('whichPartial', () => {
  const returnPartial = process.env.NODE_ENV === 'production' ?   Handlebars.compile(suppFilesProd) : Handlebars.compile(suppFiles)
  return returnPartial
});
hbs.registerHelper('complexDiscount', (...value) => {
 const data = value.filter((i) => isNumber(i))
 return data.length > 0 ? data.reduce((a, b) => a -b) : 0
});
hbs.registerPartial('nav', Handlebars.compile(nav))router.get('/products', (req, res) => {
 res.render('index', {
  title: 'Buy cool new products',
  products
 })
});

In the above code nav partial is the Navigation menu code file which is common across all the website pages. So we are registering it as partial and use it in all the hbs files. So you don’t have to write the same code on all the pages which are redundant.

“Which” partial is used to decide dynamically what data is registered as partial based on the node environment. This is useful when you want analytics or some other code that is only required in the production environment.

A complex Discount register is used when you want to send n parameters to function. let’s take an example, suppose you are giving 1 discount to the first person & 3 different discounts to another person. “…value” expects any number of parameters.

Conclusion:

Handlebars simplify your life by removing the redundant code, by making templates. Conditional syntax, looping, Helpers & Partials make the static page to dynamic. To learn how to use Handlebars in SendGrid refer here.

One comment

  1. Pingback: PDF Generation in Node.js using two ways | Noob2Geek

Leave a Reply

Your email address will not be published.