ericf / express-handlebars

A Handlebars view engine for Express which doesn't suck.
BSD 3-Clause "New" or "Revised" License
2.31k stars 384 forks source link

Add usage docs on Handlebars helpers #7

Closed ericf closed 11 years ago

ericf commented 11 years ago

There currently is not much information about how to use and register Handlebars helper functions with this module. Since it doesn't unique by segmenting helpers between ExpressHandlebars instances, there needs to be better documentation.

robdodson commented 11 years ago

Could you post a code snippet on how to do this? I'm a little lost on this one point. Should I require handlebars and start sticking them on its helpers object...?

ericf commented 11 years ago

When creating an ExpressHandlebars instance you can pass an object of helpers: https://github.com/ericf/express3-handlebars#helpers

These helpers are mixed together with the built in Handlebars helpers. Currently, passing in your custom helper functions is only convenient to do during. But if you have a reference to your ExpressHandlebars instance you can simply add properties to its helpers object: https://github.com/ericf/express3-handlebars#using-instances

robdodson commented 11 years ago

So would something like this be correct:

var Handlebars = require('handlebars');
var hbs = exphbs.create({ /* config */ });
hbs.registerHelper('link', function(text, url) {
  text = Handlebars.Utils.escapeExpression(text);
  url  = Handlebars.Utils.escapeExpression(url);

  var result = '<a href="' + url + '">' + text + '</a>';

  return new Handlebars.SafeString(result);
});
robdodson commented 11 years ago

I realize now that the above is incorrect. I'd need to do something like this:

var hbs = exphbs.create({
  helpers: require('path/to/helpers')
});

But I'm not sure how I'd be able to pass Handlebars into my helpers module because the handlebars property is only available on the created ExpressHandlebars instance. Currently my helpers module looks like this:

module.exports = function(Handlebars) {
  return {
    link: function(text, url) {
      text = Handlebars.Utils.escapeExpression(text);
      url  = Handlebars.Utils.escapeExpression(url);
      var result = '<a href="' + url + '">' + text + '</a>';
      return new Handlebars.SafeString(result);
  }
};

So for now I think I'm going to have to require handlebars separately, pass it to my helpers and then pass both handlebars and the helpers to ExpressHandlebars:

var Handlebars = require('handlebars');
var hbs = exphbs.create({
  handlebars: Handlebars,
  helpers: require('path/to/helpers')(Handlebars)
});

Do you know of a better way that I'm overlooking?

ericf commented 11 years ago

That looks good to me! This is what I was going to suggest.

If you wanted to simplify it, you could always assume you're going to use the main Handlebars module provided on npm and have your "path/to/helpers" module require('handlebars') at the top.

The reason ExpressHandlebars manages helpers in this way is to segment them from polluting other possible Handlebars users in the same process.

I also have an open issue to make it possible to pass specific helpers during rendering, it would be great to get your feedback on #3.

robdodson commented 11 years ago

Thanks for the follow up! We actually switched back to EJS for other reasons. If I get to use Handlebars again I'll take a look at #3

matthew-dean commented 10 years ago

I ran into this too. The current setup seems overly complex when trying to create helpers that reference the "Handlebars" instance to do things like Handlebars.SafeString.