Search code examples
javascriptnode.jsexpresshandlebars.jsexpress-handlebars

Missing handlebars helper error when using helper in partials. express-handlebars


I have registered helpers using express-handlebars like this:

const { create } = require("express-handlebars");
//Sets our app to use the handlebars engine
const hbs = create({
  helpers: require("./config/handlebars-helpers"),
});
app.engine("handlebars", hbs.engine);
app.set("view engine", "handlebars");
app.set("views", "./views");

And these are my helpers


// handlebar-helbers

const Handlebars = require("handlebars");
const fs = require("fs");
const path = require("path");

module.exports = {
  whichPartial(ui_type, code_name, data) {
    console.log(ui_type, code_name);
    let partial = fs
      .readFileSync(
        path.join(
          __dirname,
          `../../views/partials/${ui_type}/${code_name}/index.handlebars`
        )
      )
      .toString();
    console.log(partial);
    return Handlebars.compile(partial)({
      data: data
        ? {
            ...data,
          }
        : {},
    });
  },
  if_eq(a, b, opts) {
    if (a === b) {
      return opts.fn(this);
    } else {
      return opts.inverse(this);
    }
  },
  times(n, block) {
    var accum = "";
    for (var i = 0; i < n; ++i) accum += block.fn(i);
    return accum;
  },
};

But whenever I use a helper inside a partial it says the helper is missing. But it works inside main handlebars files.

I am not able to figure out the reason. If someone would help me it would be great.


Solution

  • The Handlebars helpers you are exporting from ./config/handlebars-helpers are made available to your app's Handlebars engine when you register them in your hbs = create call.

    However, the partials that you return from your whichPartial helper are compiled with a different Handlebars instance - one that has no helpers registered with it.

    I would advise against creating separate Handlebars instances in this manner. express-handlebars will already compile all of the partials in your views/partials directory.

    It seems the purpose of your whichPartial helper is to allow the calling code to specify the directory parts. You can still achieve this, but without the compilation, by simply returning the filepath string from the whichPartial helper. It becomes:

    whichPartial(ui_type, code_name) {
      return `${ui_type}/${code_name}/index`;
    },
    

    And the template code to call it is:

    {{> (whichPartial "your_ui_type" "your_code_name")}}