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

Dynamic Partials #241

Closed
ghost opened this issue Aug 5, 2012 · 4 comments
Closed

Dynamic Partials #241

ghost opened this issue Aug 5, 2012 · 4 comments

Comments

@ghost
Copy link

ghost commented Aug 5, 2012

Update: please see pull request for new solution: #242.

Hi,

I might be missing something obvious but can't think of a way to dynamically render a partial based on a value. For example, given the view below:

{
  items: [
    { type: 'image', title: 'Some title' },
    { type: 'text', content: 'Some text' }
  ]
}

I want to dynamically render a partial based on the 'type' key:

{{#items}}
   {{> {{type}} }}
{{/items}}

This obviously won't work but I thing there needs to be some way of doing this. Not sure what the syntax would be, something like the following(?):

{{#items}}
   {{@type}}
{{/items}}

or even...

{{>items:type}}

Currently, the only way to achieve this that I can see is to do the following:

{
  items: [
    { type: 'image', title: 'Some title', is_image: true },
    { type: 'text', content: 'Some text', is_text: true }
  ]
}
{{#items}}
  {{#is_text}}
    {{>text}}
  {{/is_text}}
  {{#is_image}}
    {{>image}}
  {{/is_image?}}
{{/items}}

Someone else has come up against the same problem here: http://stackoverflow.com/questions/2932679/dynamically-render-partial-templates-using-mustache

Kind regards,

Jamie

@ghost
Copy link
Author

ghost commented Aug 5, 2012

Thinking about this a little more, how about we allow the > character to be used with collections also. It would automatically look for a partial key for each item e.g.

{
  items: [
    { type: 'image', title: 'Some title', partial: 'image.mustache' },
    { type: 'text', content: 'Some text', partial: 'text.mustache' }
  ]
}

...could be rendered using:

{{>items}}

And if you wanted more control i.e. wrap each partial, we could have:

{{#items}}
  <p>Before</p>
  {{>.}}
  <p>After</p>
{{/items}}

...or, alternate syntax (can't decide):

{{#items}}
  <p>Before</p>
  {{@partial}}
  <p>After</p>
{{/items}}

What do people think? This is a common pattern that comes up and that needs addressing.

Jamie

@thegrandpoobah
Copy link
Contributor

Mustache deals with the dynamic scenario using Higher Order Sections. Basically, you can do the following:

var partials = { text: 'hi', image: 'bye' }
var view = {
    items: [ { type: 'text' }, { type: 'image' } ],
    dyn_partial: function() {
        return function(content, renderer) {
            // note that this points to the current context
            return renderer('{{>' + Mustache.render(content, this) + '}}');
        }
    }
};
var template = '{{#items}}{{#dyn_partial}}{{type}}{{/dyn_partial}}{{/items}}';

Mustache.render(template, view, partials);

This will output:

   hibye

It is a little clunky and the behaviour of higher order sections is not so well defined in the specification, but it works if you understand the limitations and what exactly the /this/ variable is pointing to.

Hope that helps.

@ghost
Copy link
Author

ghost commented Aug 6, 2012

That's exactly why I think we need a proper solution to this common scenario as that workaround is ugly as hell.

@ghost
Copy link
Author

ghost commented Aug 6, 2012

Please see Pull Request: #242

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

No branches or pull requests

1 participant