Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Select view template by model type/object value using Ember.js

I would like to store different objects in the same controller content array and render each one using an appropriate view template, but ideally the same view.

I am outputting list objects using the code below. They are currently identical, but I would like to be able to use different ones.

<script type="text/x-handlebars">
  {{#each App.simpleRowController}}
    {{view App.SimpleRowView class="simple-row" contentBinding="this"}}
  {{/each}}
</script>

A cut-down version of the view is below. The other functions I haven't included could be used an any of the objects, regardless of model. So I would ideally have one view (although I have read some articles about mixins that could help if not).

<script>
  App.SimpleRowView = Em.View.extend({
    templateName: 'simple-row-preview',
  });
</script>

My first few tests into allowing different object types ended up with loads of conditions within 'simple-row-preview' - it looked terrible!

Is there any way of dynamically controlling the templateName or view used while iterating over my content array?

UPDATE

Thanks very much to the two respondents. The final code in use on the view is below. Some of my models are similar, and I liked the idea of being able to switch between template (or a sort of 'state') in my application.

<script>
  App.SimpleRowView = Em.View.extend({
    templateName: function() {
      return Em.getPath(this, 'content.template');
    }.property('content.template').cacheable(),
    _templateChanged: function() {
      this.rerender();
    }.observes('templateName'),
    // etc.
  });
</script>
like image 203
joevallender Avatar asked Apr 03 '12 18:04

joevallender


2 Answers

You can make templateName a property and then work out what template to use based on the content.

For example, this uses instanceof to set a template based on the type of object:

App.ItemView = Ember.View.extend({     templateName: function() {         if (this.get("content") instanceof App.Foo) {             return "foo-item";         } else {             return "bar-item";         }     }.property().cacheable() }); 

Here's a fiddle with a working example of the above: http://jsfiddle.net/rlivsey/QWR6V/

like image 184
rlivsey Avatar answered Sep 30 '22 17:09

rlivsey


Based on the solution of @rlivsey, I've added the functionality to change the template when a property changes, see http://jsfiddle.net/pangratz666/ux7Qa/

App.ItemView = Ember.View.extend({
    templateName: function() {
        var name = Ember.getPath(this, 'content.name');
        return (name.indexOf('foo') !== -1) ? 'foo-item' : 'bar-item';
    }.property('content.name').cacheable(),

    _templateChanged: function() {
        this.rerender();
    }.observes('templateName')
});
like image 40
pangratz Avatar answered Sep 30 '22 19:09

pangratz