Closed justinledouxweb closed 8 years ago
Dynamic partials are supported in Handlebars 3.0. See: https://github.com/wycats/handlebars.js/pull/941
So you would do:
{{#each modules}}
{{> (this.name) }}
{{/each}}
@ericf I must be missing something then...
TypeError: undefined is not a function
at Object.eval (eval at <anonymous> (/Users/justinledoux/Documents/node/qsPortal/node_modules/express-handlebars/node_modules/handlebars/dist/cjs/handlebars/compiler/javascript-compiler.js:209:23), <anonymous>:5:90)
at prog (/Users/justinledoux/Documents/node/qsPortal/node_modules/express-handlebars/node_modules/handlebars/dist/cjs/handlebars/runtime.js:178:15)
at execIteration (/Users/justinledoux/Documents/node/qsPortal/node_modules/express-handlebars/node_modules/handlebars/dist/cjs/handlebars/base.js:133:19)
at Object.<anonymous> (/Users/justinledoux/Documents/node/qsPortal/node_modules/express-handlebars/node_modules/handlebars/dist/cjs/handlebars/base.js:142:11)
at Object.eval (eval at <anonymous> (/Users/justinledoux/Documents/node/qsPortal/node_modules/express-handlebars/node_modules/handlebars/dist/cjs/handlebars/compiler/javascript-compiler.js:209:23), <anonymous>:5:34)
at ret (/Users/justinledoux/Documents/node/qsPortal/node_modules/express-handlebars/node_modules/handlebars/dist/cjs/handlebars/runtime.js:144:30)
at ret (/Users/justinledoux/Documents/node/qsPortal/node_modules/express-handlebars/node_modules/handlebars/dist/cjs/handlebars/compiler/compiler.js:462:21)
at ExpressHandlebars._renderTemplate (/Users/justinledoux/Documents/node/qsPortal/node_modules/express-handlebars/lib/express-handlebars.js:247:12)
at ExpressHandlebars.<anonymous> (/Users/justinledoux/Documents/node/qsPortal/node_modules/express-handlebars/lib/express-handlebars.js:173:21)
This is what I have in the code:
{{#each portal.modules}}
{{> (this.url) }}
{{/each}}
(portal
is a res.locals
variable available on the request to the page I am hitting).
If I print {{this.url}}
I am getting the proper values (alerts, mapping, news).
So I didn't try to the code myself… let me know what you figure out.
Looking at the unit tests the subexpression needs to be a helper. Something like this:
var app = express();
app.set('view engine', 'hbs');
app.engine('hbs', exphbs({
helpers: {
partial: function (name) {
return name;
}
}
}));
{{#each modules}}
{{> (partial this.name) }}
{{/each}}
Hi Justin! I took a look at this, and it appears to be a quirk of how Handlebars processes subexpressions:
"Subexpressions do not resolve variables so whichPartial must be a function."
In your code, this.url
is (presumably) a string, when it needs to be a function returning a string.
modules: [
{ url: '...' },
{ url: '...'}
]
needs to be:
modules: [
{ url: function() { return '...'; } },
{ url: function() { return '...'; } },
]
Kinda awkward. Alternatively, you could perform a lookup
on the value, like so:
{{#each portal.modules}}
{{> ( lookup . 'this.url') }}
{{/each}}
I've tested both these approaches in v.2.0.1 of express-handlebars, and both work without any custom helpers required. I'm using lookup
in my own code, since it doesn't require polluting an object with a ton of anonymous functions. :smile:
Apparently your dynamic partials need to parsed as a function which returns a string.
I'm having trouble with dynamic partials as well. I thought I was doing it correctly but I keep receiving a partial not found error. Oddly, the error disappears if I mention the partial in a commented handlebars statement, as if that commented statement loaded the template, so now the dynamic loading works. Please see the details here:
http://stackoverflow.com/questions/36438434/handlebars-and-node-dynamic-partial-not-found
Can you anyone help?
If you're using the handlebar-helpers library you can use a standard string function such as lowercase
. It might not do anything but it returns a function and fixes this niggle.
{{> (lowercase this.url)}}
Hi,
I have been looking for a simple way to dynamically render partials based on a value in an
{{#each ...}}
loop.For example:
This would allow me to load partials based on data rather than putting a lot of logic in the template.