Skip to content

Instantly share code, notes, and snippets.

@ThisIsMissEm
Created March 5, 2024 16:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ThisIsMissEm/014a2d6ddb0ba53bebfb7be04870c46b to your computer and use it in GitHub Desktop.
Save ThisIsMissEm/014a2d6ddb0ba53bebfb7be04870c46b to your computer and use it in GitHub Desktop.
If you've ever needed a `global` value in an express.js application using handlebars.js, then you can do this nasty hack. This allows you to write handlebars templates with variables like `{{@exphbs.data.X}}` where `X` is a property on `res.locals.globals`.
import expressHandlebars from "express-handlebars";
// setup handlebars for view templates:
const hbs = expressHandlebars.create({
extname: ".hbs",
helpers: { /* ... handlebars helpers */ },
});
// The express handlebars package in theory allows setting values in the
// handlebars `data` side-channel, however, the the way to set this value is via
// the options to `expressHandlebars.create` which cannot access the request
// context / request locals.
//
// As such, we need to augment the template engine, to extract the
// res.locals.globals value from the template engine's options hash
// (options._locals.globals), and set the data side channel to that value.
app.engine("hbs", function (viewPath, options, callback) {
return hbs.engine(
viewPath,
{
...options,
// The express handlebars package has bad types, and the `data` property
// can only be set via setting it directly on `ConfigOptions`, not on
// `ConfigOptions.runtimeOptions`
// @ts-ignore
data: options._locals.globals,
},
callback,
);
});
// Setup `options._locals.globals` used above:
app.use((_req, res, next) => {
res.locals.globals = {};
next();
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment