Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Including partials dynamically #121

Closed
justinledouxweb opened this issue Apr 7, 2015 · 8 comments
Closed

Including partials dynamically #121

justinledouxweb opened this issue Apr 7, 2015 · 8 comments
Labels

Comments

@justinledouxweb
Copy link

Hi,

I have been looking for a simple way to dynamically render partials based on a value in an {{#each ...}} loop.

For example:

{{#each modules}}
    {{> @exphbs.partials[ this.name ] }}
{{/each}}

This would allow me to load partials based on data rather than putting a lot of logic in the template.

@ericf
Copy link
Owner

ericf commented Apr 8, 2015

Dynamic partials are supported in Handlebars 3.0. See: handlebars-lang/handlebars.js#941

So you would do:

{{#each modules}}
    {{> (this.name) }}
{{/each}}

@ericf ericf added the support label Apr 8, 2015
@justinledouxweb
Copy link
Author

@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).

@ericf
Copy link
Owner

ericf commented Apr 9, 2015

So I didn't try to the code myself… let me know what you figure out.

@ericf
Copy link
Owner

ericf commented Apr 9, 2015

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}}

@samuelfine
Copy link

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. 😄

@ghost
Copy link

ghost commented Mar 20, 2016

Apparently your dynamic partials need to parsed as a function which returns a string.

@flyingL123
Copy link

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?

@sidonaldson
Copy link

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)}}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

5 participants