Closed tuxsudo closed 9 years ago
The partials won't be available on Handlebars.partials
unless you explicitly register them there as this package does not want to mess around with the global partials registry to avoid conflicts from other code running in the process.
That said, I think they should be accessible via options.partials
. Can you see if they're there?
Also note that they are named with path-like syntax. So if you have multiple nested dirs of partials their name will be something like: "user/avatar"
, which corresponds to views/partials/user/avatar.hbs
.
That said, I think they should be accessible via options.partials. Can you see if they're there?
By options.partials
, do you mean the same helper options
object where you typically find options.hash
and options.fn
(for block helpers)? If so, it's not there...
Yeah you're right they're not there; bummer.
The quickest way to hack this in would be to override the private _renderTemplate()
method.
var app = express(),
hbs = exphbs.create({ /* config */ });
// Register `hbs.engine` with the Express app.
app.engine('handlebars', hbs.engine);
app.set('view engine', 'handlebars');
// Override private `_renderTemplate()` method to expose partials.
hbs._renderTemplate = function (template, context, options) {
// Expose partials on `options.data.partials` in helpers.
options.data || (options.data = {});
options.data.partials = options.partials;
template(context, options);
};
Now inside your helpers, you can access the partials via options.data.partials
.
Let me know if that if this fixes your issue. And I'll think more about how to integrate this into this package without requiring the hack above. I'm also interested to see if anyone else is wanting to do a similar thing with invoking partials via helpers…
We want to use Handlebars both on the server and the client interchangeably and/or simultaneously and use it the same way. On the clientside, there is the global Handlebars object which knows all the helpers & partials; we want to mimic that functionality serverside.
I ended up doing something like the following to make a 'Global' like Handlebars Object where the Handlebars' helpers are aware of the partials:
var Handlebars = require('handlebars'),
ExpressHandleBars = require('express-handlebars').create({
layoutsDir: "views/layouts/",
partialsDir: "views/partials/"
handlebars: Handlebars
});
ExpressHandleBars.getPartials().then(function (partials) {
Handlebars.partials = partials;
var helpers = require("./views/helpers")( Handlebars );
Object.keys(helpers).forEach(function(helper) {
Handlebars.registerHelper(helper, helpers[helper] );
});
});
The helpers file (./views/helpers
) looks something like:
module.exports = function(Handlebars) {
return {
"helper": function (options) {
// The `Handlebars` object now acts "global" and with knowledge of all partials and helpers.
}
}
Still feels somewhat hacky, but it works. Thoughts?
I'm already referencing any helpers from Handlebars.helpers
and mixing them with and local or per-render helpers that are specified.
I'm willing to entertain the idea of doing something similar for partials, but it would be up to you to globally register partials with Handlebars since that's something this package won't be doing in order to maintain a sandbox.
That would be awesome. :)
@TuxSudo also if you're up for it, feel free to open a PR to implement this feature :smile:
This seems very much related to #101, and in PR #105 I'm now passing along the partials
to the data channel during rendering making them available inside of helpers via options.data.ExpressHandlebars.partials
.
Let me know if you think that will solve what you're after here, and if so, I'll close this out once #105 is merged.
Not particularly, but that's ok. The goal is to allow development of helpers and partials that work both server and clientside. Clientside, handlebars puts partials at Handlebars.partials
. So, I'd still have to register them globally anyway with the proposed solution. But I will close this and potentially submit a pull request later.
Thanks for your work on this. :+1:
@tuxsudo thankyou for the hint. I was wondering how can I access Handlebars instance in my helpers file when using express-handlebars package.
this is the hack I used
// app.js
var hbs = exhbs.create({
defaultLayout: 'main',
helpers: require('./lib/hbs-helpers'),
// other options
});
and in lib/hbs-helpers.js
Handlebars = require('handlebars'); // the official handlebars package
module.exports = (function(Handlebars) {
fallback: function(actual, defaultValue) {
var out = actual || defaultVal;
return new Handlebars.SafeString(out); // now I can access Handlebars instance
}
})(Handlebars);
This is a hack as I am not good with documentations so is there an integration with express-handlebars.
We want to be able to render partials from inside helpers. For example, in our global helpers file, when we try something like:
That partial
partial-name
is not available becauseHandlebars.partials
is an empty object{}
.What is the best way to create/import/inject the
Handlebars.partials
object (as defined in thepartialsDir
option) so our helpers can instantiate them?Thanks in advance!