Register and manage Handlebars helper functions, including asynchronous helpers with callback support for complex operations.
Register standard Handlebars helpers that return values immediately.
/**
* Register synchronous helper function
* @param name - Helper name to use in templates
* @param helper - Helper function that returns a value
*/
function registerHelper(name, helper);Usage Examples:
const hbs = require('hbs');
// Simple string helper
hbs.registerHelper('uppercase', function(str) {
return str.toUpperCase();
});
// Helper with multiple parameters
hbs.registerHelper('link_to', function(title, url) {
return '<a href="' + url + '">' + title + '</a>';
});
// Block helper
hbs.registerHelper('list', function(items, options) {
let out = '<ul>';
for (let i = 0; i < items.length; i++) {
out += '<li>' + options.fn(items[i]) + '</li>';
}
return out + '</ul>';
});
// Helper with context access
hbs.registerHelper('conditional', function(v1, operator, v2, options) {
switch (operator) {
case '==':
return (v1 == v2) ? options.fn(this) : options.inverse(this);
case '!=':
return (v1 != v2) ? options.fn(this) : options.inverse(this);
default:
return options.inverse(this);
}
});In Templates:
<!-- Simple helper -->
{{uppercase "hello world"}}
<!-- Output: HELLO WORLD -->
<!-- Helper with parameters -->
{{{link_to "Google" "https://google.com"}}}
<!-- Output: <a href="https://google.com">Google</a> -->
<!-- Block helper -->
{{#list people}}
{{name}} - {{age}}
{{/list}}
<!-- Conditional helper -->
{{#conditional score ">=" 90}}
Grade: A
{{else}}
Grade: B or lower
{{/conditional}}Register helpers that perform asynchronous operations like API calls, file I/O, or database queries.
/**
* Register asynchronous helper function
* @param name - Helper name to use in templates
* @param helper - Helper function that calls callback with result
*/
function registerAsyncHelper(name, helper);Usage Examples:
const hbs = require('hbs');
const fs = require('fs');
// File reading helper
hbs.registerAsyncHelper('readFile', function(filename, callback) {
fs.readFile(filename, 'utf8', (err, data) => {
if (err) {
callback('Error reading file');
} else {
callback(data);
}
});
});
// API call helper
hbs.registerAsyncHelper('fetchUserName', function(userId, callback) {
// Simulate API call
setTimeout(() => {
const users = { 1: 'Alice', 2: 'Bob', 3: 'Charlie' };
callback(users[userId] || 'Unknown User');
}, 100);
});
// Helper with multiple parameters
hbs.registerAsyncHelper('formatDate', function(date, format, callback) {
// Simulate async date formatting
process.nextTick(() => {
const formatted = new Date(date).toLocaleDateString();
callback(formatted);
});
});
// Helper with context access
hbs.registerAsyncHelper('checkPermission', function(action, callback) {
// this.user would be available from template context
const user = this.user || {};
// Simulate permission check
setTimeout(() => {
const hasPermission = user.permissions && user.permissions.includes(action);
callback(hasPermission ? 'Allowed' : 'Denied');
}, 50);
});In Templates:
<!-- File content helper -->
<pre>{{readFile "config.txt"}}</pre>
<!-- User data helper -->
<p>Welcome, {{fetchUserName userId}}!</p>
<!-- Date formatting helper -->
<span>Created: {{formatDate createdAt "short"}}</span>
<!-- Permission helper -->
<div class="status">{{checkPermission "admin"}}</div>Direct access to the underlying Handlebars instance for advanced operations.
/**
* Direct access to Handlebars instance
* @type HandlebarsStatic
*/
handlebars;Usage Examples:
const hbs = require('hbs');
// Access Handlebars directly
const SafeString = hbs.handlebars.SafeString;
const Utils = hbs.handlebars.Utils;
// Use Handlebars SafeString in helpers
hbs.registerHelper('safeHtml', function(html) {
return new SafeString(html);
});
// Use Handlebars utilities
hbs.registerHelper('escapeExpression', function(str) {
return hbs.handlebars.Utils.escapeExpression(str);
});
// Register helper on Handlebars directly (not recommended)
hbs.handlebars.registerHelper('directHelper', function() {
return 'Registered directly';
});All helpers receive the current template context as this and access to Handlebars options.
hbs.registerHelper('contextExample', function() {
// Access current template data
console.log('Current context:', this);
// Access specific properties
return this.someProperty || 'default';
});Block helpers receive an options parameter with additional functionality:
hbs.registerHelper('blockExample', function(options) {
// options.fn - renders the block content
// options.inverse - renders the {{else}} content
// options.hash - contains hash parameters
// options.data - contains @index, @first, @last, etc.
return options.fn(this); // Render block content
});Helpers can accept named parameters via hash notation:
hbs.registerHelper('withDefaults', function(options) {
const defaults = {
color: 'blue',
size: 'medium',
...options.hash // Override with provided values
};
return `<div class="${defaults.color} ${defaults.size}">Content</div>`;
});In Template:
{{withDefaults color="red" size="large"}}
<!-- Output: <div class="red large">Content</div> -->Asynchronous helpers are automatically coordinated so templates wait for all async operations to complete before rendering.
Async Flow:
Multiple Async Helpers:
hbs.registerAsyncHelper('slowHelper1', function(callback) {
setTimeout(() => callback('Result 1'), 100);
});
hbs.registerAsyncHelper('slowHelper2', function(callback) {
setTimeout(() => callback('Result 2'), 200);
});In Template:
<p>{{slowHelper1}} and {{slowHelper2}}</p>
<!-- Template waits for both helpers, then outputs: -->
<!-- <p>Result 1 and Result 2</p> -->