express-handlebars icon indicating copy to clipboard operation
express-handlebars copied to clipboard

Get the handlebar instance

Open bavarianbytes opened this issue 6 years ago • 5 comments

I'm trying to extend handlebars with helpers from https://github.com/shannonmoeller/handlebars-layouts. To register the helpers i need access to the underlying handlebars instance of express-handlebars. How can i get the instance?

bavarianbytes avatar Feb 12 '19 19:02 bavarianbytes

It is exposed via the handlebars attribute. So for this module, I think this would work:

const layouts = require('handlebars-layouts');
const hbs = exphbs.create();

layouts.register(hbs.handlebars);

romellem avatar Feb 20 '19 15:02 romellem

The code above allows handlebars-layouts to register, but doesn't allow it to work with express-handlebars.

Calling {{#extend "layouts/foo"}} fails with the error

Error: Missing partial: 'layouts/foo'
    at Object.extend (/app/node_modules/handlebars-layouts/index.js:120:11)
    at Object.eval [as main] (eval at createFunctionContext (/app/node_modules/handlebars/dist/cjs/handlebars/compiler/javascript-compiler.js:257:23), <anonymous>:5:92)
    at main (/app/node_modules/handlebars/dist/cjs/handlebars/runtime.js:175:32)
    at ret (/app/node_modules/handlebars/dist/cjs/handlebars/runtime.js:178:12)
    at ret (/app/node_modules/handlebars/dist/cjs/handlebars/compiler/compiler.js:526:21)
    at ExpressHandlebars._renderTemplate (/app/node_modules/express-handlebars/lib/express-handlebars.js:247:12)
    at ExpressHandlebars.<anonymous> (/app/node_modules/express-handlebars/lib/express-handlebars.js:173:21)

This is how I'm setting the two up

const path = require('path')
const express = require('express')
const exphbs = require('express-handlebars')
const layouts = require('handlebars-layouts')
const handlerbarsHelpers = require('./handlebars-helpers')

const app = express()

const hbs = exphbs.create({
  helpers: handlerbarsHelpers,
  extname: 'hbs',
  partialsDir: path.join(__dirname, 'views', 'partials')
})

hbs.getPartials().then(partials => console.log(Object.keys(partials)))

app.engine('.hbs', hbs.engine)
app.set('view engine', '.hbs')
app.set('views', path.join(__dirname, 'views'))

layouts.register(hbs.handlebars)

app.get('/foo', (req, res) => {
  res.render('foo')
})

ghost avatar Apr 10 '19 14:04 ghost

I can fix the issue by manually registering the partial with handlebars. Is there a way to avoid that?

hbs.getPartials().then(partials => hbs.handlebars.registerPartial('layouts/foo', partials['layouts/foo']))

ghost avatar Apr 10 '19 14:04 ghost

You could also configure your handlebars instance separately then pass that in via the handlebars config option when creating your express-handlebars instance.

Maybe something like this?

const handlebars = require('handlebars');
const layouts = require('handlebars-layouts');
const exphbs = require('express-handlebars');

handlebars.registerHelper(layouts(handlebars));

const hbs = exphbs.create({
  handlebars: handlebars,
  // ... Other config options here (helpers, partialsDir, etc.)
});

romellem avatar Apr 11 '19 18:04 romellem

@romellem With your solution, the partials still need to be registered manually, as @dowtkrob suggested above. Otherwise they're not found.

mrkvon avatar May 08 '19 18:05 mrkvon