Skip to main content

Express Template Helpers

Introduction

Template helpers are functions that you can use within your template files to transform data or perform operations that make your views more dynamic. They act as a bridge between your controllers and views, allowing you to keep your templates clean and your logic organized.

In Express applications, different templating engines (like EJS, Handlebars, Pug) provide different ways to implement these helpers. They're particularly useful when you need to:

  • Format data (dates, currency, text)
  • Perform conditional logic that's too complex for template syntax
  • Create reusable blocks of template code
  • Implement functionality that would otherwise clutter your templates

In this lesson, we'll explore how to create and use template helpers in Express applications with various templating engines.

Understanding Template Helpers

Template helpers are essentially JavaScript functions that you can call from within your template files. They can take parameters, perform operations, and return values that get rendered in the final HTML.

Why Use Template Helpers?

  1. Separation of concerns: Keep complex logic out of your templates
  2. Code reusability: Define a function once and use it across multiple templates
  3. Cleaner templates: Make your templates more readable by abstracting away complex operations
  4. Maintainable code: Easier to update functionality in a central location

Template Helpers in Different Engines

Let's look at how to implement helpers in three popular templating engines: Handlebars, EJS, and Pug.

Handlebars Helpers

Handlebars is particularly good at using helpers, as they're a core part of its design.

Basic Setup

javascript
const express = require('express');
const exphbs = require('express-handlebars');
const app = express();

// Initialize Handlebars
const hbs = exphbs.create({
// Define your helpers here
helpers: {
// Format a date
formatDate: function(date) {
return new Date(date).toLocaleDateString();
},
// Capitalize a string
capitalize: function(text) {
return text.charAt(0).toUpperCase() + text.slice(1);
}
}
});

app.engine('handlebars', hbs.engine);
app.set('view engine', 'handlebars');

Using Helpers in Templates

handlebars
<div class="article">
<h2>{{capitalize title}}</h2>
<p>Published on: {{formatDate publishDate}}</p>
<div class="content">{{content}}</div>
</div>

Input Data:

javascript
{
title: "learning express templates",
publishDate: "2023-05-15",
content: "This is an article about Express templates."
}

Output HTML:

html
<div class="article">
<h2>Learning express templates</h2>
<p>Published on: 5/15/2023</p>
<div class="content">This is an article about Express templates.</div>
</div>

EJS Helpers

EJS doesn't have built-in support for helpers like Handlebars, but you can pass helper functions to your templates through the render method.

Basic Setup

javascript
const express = require('express');
const app = express();

app.set('view engine', 'ejs');

// Create helper functions
const helpers = {
formatDate: function(date) {
return new Date(date).toLocaleDateString();
},
capitalize: function(text) {
return text.charAt(0).toUpperCase() + text.slice(1);
}
};

// Use middleware to make helpers available to all templates
app.use((req, res, next) => {
res.locals.helpers = helpers;
next();
});

Using Helpers in Templates

ejs
<div class="article">
<h2><%= helpers.capitalize(title) %></h2>
<p>Published on: <%= helpers.formatDate(publishDate) %></p>
<div class="content"><%= content %></div>
</div>

Pug Helpers

Like EJS, Pug doesn't have a built-in helper system, but you can pass helper functions through locals.

Basic Setup

javascript
const express = require('express');
const app = express();

app.set('view engine', 'pug');

// Create helper functions
const helpers = {
formatDate: function(date) {
return new Date(date).toLocaleDateString();
},
capitalize: function(text) {
return text.charAt(0).toUpperCase() + text.slice(1);
}
};

// Make helpers available to all templates
app.use((req, res, next) => {
res.locals.helpers = helpers;
next();
});

Using Helpers in Templates

pug
div.article
h2= helpers.capitalize(title)
p Published on: #{helpers.formatDate(publishDate)}
div.content= content

Creating Advanced Helpers

Let's create some more useful template helpers for real-world applications.

Currency Formatter

javascript
helpers.formatCurrency = function(amount, currency = 'USD') {
return new Intl.NumberFormat('en-US', {
style: 'currency',
currency: currency
}).format(amount);
};

Usage in template:

handlebars
<div class="product">
<h3>{{product.name}}</h3>
<p class="price">{{formatCurrency product.price}}</p>
</div>

Truncate Text

javascript
helpers.truncate = function(text, length = 100) {
if (text.length <= length) return text;
return text.substring(0, length) + '...';
};

Usage:

handlebars
<div class="summary">
<p>{{truncate article.content 150}}</p>
</div>

Conditional Class Helper

javascript
helpers.ifEqual = function(a, b, options) {
if (a === b) {
return options.fn(this);
}
return options.inverse(this);
};

Usage in Handlebars:

handlebars
<li class="nav-item {{#ifEqual currentPage 'home'}}active{{/ifEqual}}">
<a href="/">Home</a>
</li>

List Iterator Helper

javascript
helpers.list = function(items, options) {
let html = '<ul>';
for (let i = 0; i < items.length; i++) {
html += '<li>' + options.fn(items[i]) + '</li>';
}
html += '</ul>';
return html;
};

Usage:

handlebars
{{#list users}}
{{name}} ({{email}})
{{/list}}

Real-world Example: Blog Template

Let's see a more comprehensive example of using template helpers in a blog application:

Setup the Helpers

javascript
const express = require('express');
const exphbs = require('express-handlebars');
const app = express();

// Initialize Handlebars with custom helpers
const hbs = exphbs.create({
helpers: {
formatDate: function(date) {
const options = { year: 'numeric', month: 'long', day: 'numeric' };
return new Date(date).toLocaleDateString('en-US', options);
},
excerpt: function(content, length = 150) {
if (content.length <= length) return content;
return content.substring(0, length) + '...';
},
timeToRead: function(content) {
// Average reading speed: 200 words per minute
const wordsPerMinute = 200;
const words = content.trim().split(/\s+/).length;
const minutes = Math.ceil(words / wordsPerMinute);
return minutes + ' min read';
},
toLowerCase: function(text) {
return text.toLowerCase();
},
tagBadgeClass: function(tag) {
// Return different badge classes based on tag
const classes = {
javascript: 'badge-warning',
node: 'badge-success',
express: 'badge-info',
default: 'badge-secondary'
};
return classes[tag.toLowerCase()] || classes.default;
}
}
});

app.engine('handlebars', hbs.engine);
app.set('view engine', 'handlebars');

Using in Blog Post Template

handlebars
<div class="blog-post">
<h1>{{post.title}}</h1>

<div class="post-meta">
<span class="date">{{formatDate post.publishDate}}</span>
<span class="read-time">{{timeToRead post.content}}</span>
<span class="author">By {{post.author}}</span>
</div>

<div class="tags">
{{#each post.tags}}
<span class="badge {{tagBadgeClass this}}">{{toLowerCase this}}</span>
{{/each}}
</div>

{{#if summary}}
<div class="summary">
<p><strong>Summary: </strong>{{excerpt post.content 200}}</p>
</div>
{{/if}}

<div class="content">
{{post.content}}
</div>
</div>

Example Data:

javascript
const post = {
title: "Getting Started with Express Template Helpers",
publishDate: "2023-09-15",
author: "Jane Developer",
tags: ["JavaScript", "Express", "Node"],
content: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam euismod, nisl eget aliquam ultricies, nunc nisl ultricies nunc, quis ultricies nisl nisl eget aliquam ultricies, nunc nisl ultricies nunc, quis ultricies nisl..."
// (imagine this is much longer)
};

res.render('blog/post', { post, summary: true });

Best Practices

  1. Keep helpers simple and focused: Each helper should do one thing well.
  2. Document your helpers: Add comments to explain what each helper does, its parameters, and return values.
  3. Organize helpers by category: As your application grows, consider organizing helpers into categories.
  4. Test helpers separately: Write unit tests for your helper functions.
  5. Handle errors gracefully: Make sure your helpers don't throw errors that could break the template rendering.
  6. Be mindful of performance: Complex operations in helpers can slow down rendering.

Creating Organized Helper Files

For larger applications, it's good practice to organize your helpers into separate files:

javascript
// helpers/dateHelpers.js
module.exports = {
formatDate: function(date) {
return new Date(date).toLocaleDateString();
},
timeAgo: function(date) {
// Implementation for relative time
}
};

// helpers/textHelpers.js
module.exports = {
capitalize: function(text) {
return text.charAt(0).toUpperCase() + text.slice(1);
},
truncate: function(text, length) {
// Implementation for text truncation
}
};

// index.js (combine all helpers)
const dateHelpers = require('./dateHelpers');
const textHelpers = require('./textHelpers');

module.exports = {
...dateHelpers,
...textHelpers
};

Then register them with your templating engine:

javascript
const allHelpers = require('./helpers');

const hbs = exphbs.create({
helpers: allHelpers
});

app.engine('handlebars', hbs.engine);

Summary

Template helpers are powerful tools for enhancing your Express templates. They allow you to:

  • Keep your templates clean and focused on presentation
  • Reuse formatting and logic across multiple views
  • Handle complex operations outside of your templates
  • Create a more maintainable codebase

Different templating engines have different approaches to implementing helpers, but the core concept remains the same: move complex logic into functions that can be called from your templates.

By mastering template helpers, you'll build more maintainable, readable, and flexible Express applications.

Additional Resources

Exercises

  1. Create a helper function that formats phone numbers (e.g., from "1234567890" to "(123) 456-7890").
  2. Build a pagination helper that generates pagination links based on the current page and total pages.
  3. Implement a "highlightSearch" helper that wraps search terms in HTML <mark> tags within a body of text.
  4. Create a helper that generates a random placeholder image URL based on dimensions.
  5. Build a set of helpers for a e-commerce site that handle product pricing, discounts, and availability messages.


If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)