Register and manage Handlebars partial templates, including bulk registration from directories with custom naming transformations.
Register individual partial templates by name and content.
/**
* Register single partial template
* @param name - Partial name to use in templates
* @param template - Template string content
*/
function registerPartial(name, template);Usage Examples:
const hbs = require('hbs');
// Simple partial
hbs.registerPartial('header', '<header><h1>{{title}}</h1></header>');
// Partial with variables
hbs.registerPartial('user_card', `
<div class="user-card">
<h3>{{name}}</h3>
<p>{{email}}</p>
<span class="role">{{role}}</span>
</div>
`);
// Partial using other partials
hbs.registerPartial('page_layout', `
{{> header}}
<main>{{> content}}</main>
{{> footer}}
`);In Templates:
<!-- Use registered partials -->
{{> header title="Welcome"}}
{{> user_card name="Alice" email="alice@example.com" role="Admin"}}
<!-- Partials inherit current context -->
{{#each users}}
{{> user_card}}
{{/each}}Automatically register all partial templates from a directory with optional naming customization.
/**
* Register all partials from directory
* @param directory - Path to directory containing partial files
* @param options - Optional configuration object
* @param callback - Optional completion callback
*/
function registerPartials(directory, options, callback);Basic Usage:
const hbs = require('hbs');
const path = require('path');
// Register all partials from directory
hbs.registerPartials(path.join(__dirname, 'views/partials'));
// With callback
hbs.registerPartials(path.join(__dirname, 'views/partials'), (err) => {
if (err) {
console.error('Failed to register partials:', err);
} else {
console.log('All partials registered successfully');
}
});Directory Structure Example:
views/partials/
├── header.hbs → {{> header}}
├── footer.hbs → {{> footer}}
├── user-card.html → {{> user_card}}
├── nav menu.hbs → {{> nav_menu}}
├── social/
│ ├── twitter.hbs → {{> social/twitter}}
│ └── facebook.hbs → {{> social/facebook}}
└── forms/
├── login-form.hbs → {{> forms/login_form}}
└── contact.hbs → {{> forms/contact}}Customize how filenames are transformed into partial names using the
rename/**
* Partial registration options
* @typedef {Object} PartialOptions
* @property {Function} rename - Function to transform filename to partial name
*/
/**
* Register partials with custom naming
* @param directory - Path to directory containing partial files
* @param options - Configuration with rename function
* @param callback - Optional completion callback
*/
function registerPartials(directory, options, callback);Usage Examples:
const hbs = require('hbs');
// Default naming (spaces and hyphens become underscores)
hbs.registerPartials('./partials');
// user-profile.hbs → user_profile
// contact form.hbs → contact_form
// Custom naming: camelCase
hbs.registerPartials('./partials', {
rename: function(name) {
return name.replace(/[\s-_]+(.)/g, (match, letter) => letter.toUpperCase());
}
});
// user-profile.hbs → userProfile
// contact form.hbs → contactForm
// Custom naming: preserve hyphens, remove spaces
hbs.registerPartials('./partials', {
rename: function(name) {
return name.replace(/\s+/g, '');
}
});
// user-profile.hbs → user-profile
// contact form.hbs → contactform
// Custom naming: uppercase with prefix
hbs.registerPartials('./partials', {
rename: function(name) {
return 'PARTIAL_' + name.toUpperCase().replace(/\W/g, '_');
}
});
// user-profile.hbs → PARTIAL_USER_PROFILE
// contact form.hbs → PARTIAL_CONTACT_FORMUnderstanding how files are discovered and processed during directory registration.
File Discovery Rules:
.html.hbsNaming Transformation Process:
renameExample Transformation:
Directory: /app/views/partials
File: /app/views/partials/admin/user-form.hbs
1. Relative path: admin/user-form.hbs
2. Remove extension: admin/user-form
3. Convert slashes: admin/user-form
4. Custom rename: admin/userForm (if camelCase rename)
5. Final cleanup: admin/userForm
Partial name: {{> admin/userForm}}Partial registration is asynchronous and non-blocking, but templates wait for completion before rendering.
const hbs = require('hbs');
// Multiple registration calls are queued
hbs.registerPartials('./partials/global');
hbs.registerPartials('./partials/admin');
hbs.registerPartials('./partials/components');
// All registrations complete before template rendering
app.get('/', (req, res) => {
// This render will wait for all partials to be registered
res.render('index');
});Registration Queue:
registerPartialsPartial registration handles various error conditions gracefully.
Error Scenarios:
Example Error Handling:
hbs.registerPartials('./nonexistent-directory', (err) => {
if (err) {
console.error('Partial registration failed:', err.message);
// ENOENT: no such file or directory, open './nonexistent-directory'
}
});
// Handle partial registration in application startup
function initializePartials() {
return new Promise((resolve, reject) => {
hbs.registerPartials('./views/partials', (err) => {
if (err) {
reject(err);
} else {
resolve();
}
});
});
}
// Use in async startup
async function startApp() {
try {
await initializePartials();
console.log('Partials loaded successfully');
app.listen(3000, () => {
console.log('Server ready');
});
} catch (err) {
console.error('Failed to start app:', err);
process.exit(1);
}
}Partials inherit the current template context and can receive additional data.
Context Inheritance:
<!-- Template data: { user: { name: "Alice", role: "Admin" }, title: "Dashboard" } -->
{{> header}}
<!-- header partial has access to {{user.name}}, {{title}}, etc. -->
{{#with user}}
{{> user_profile}}
<!-- user_profile partial has access to {{name}}, {{role}} directly -->
{{/with}}Passing Additional Data:
<!-- Pass additional variables to partials -->
{{> button_primary text="Click Me" size="large"}}
<!-- Combine context and additional data -->
{{> user_card role="Guest"}}
<!-- user_card gets both inherited context AND role="Guest" -->Partials can include other partials, creating reusable component hierarchies.
Example Nested Structure:
<!-- page_layout partial -->
<!DOCTYPE html>
<html>
{{> head}}
<body>
{{> header}}
<main>
{{> content}}
</main>
{{> footer}}
</body>
</html>
<!-- header partial -->
<header>
{{> navigation}}
{{> breadcrumbs}}
</header>
<!-- navigation partial -->
<nav>
{{#each menuItems}}
{{> nav_item}}
{{/each}}
</nav>