2

Given that I have this code:

Ember.App.View = Ember.View.extend({
    templateName: "templateA"
});
Ember.App.View = Ember.View.extend({
    templateName: "templateB"
});
Ember.App.ViewC = Ember.CollectionView.extend({
    itemViewClass: "Ember.View",
    contentBinding: "SomeController"
});

Is there a way to add views with different templates to CollectionView?

Alex Navasardyan
  • 536
  • 5
  • 12
  • 1
    Maybe is better to use ContainerView but the documentation is missing right now on the emberjs.com. You have to take a look at the code and figure out how to use it. As a general thought, emberjs has poor documentation – Bogdan M. Apr 18 '12 at 19:17
  • Figured it out. It's better to use ContainerView for that. Here's the example: http://jsfiddle.net/6ksqd/1/. – Alex Navasardyan Apr 18 '12 at 19:26
  • The ContainerView documentation has been recently added : https://github.com/emberjs/ember.js/commit/290049c4624365caa15b88afbf091534de204a8b – louiscoquio Apr 18 '12 at 19:39
  • 1
    you can set the templateName on a view at any time, and it will swap the template used on the screen... so you could put some code in your views to determine which template to use at any particular time – Nicholas Franceschina Apr 18 '12 at 19:47
  • @NickFranceschina 's comment: be sure to invoke `rerender` when you change the `templateName`, see http://jsfiddle.net/pangratz666/zLWuT/ – pangratz Apr 19 '12 at 10:09

3 Answers3

6

You can make the templateName of the itemViewClass a computed property, see http://jsfiddle.net/pangratz666/vGHcD/:

App.MyView = Ember.View.extend({
    templateName: function() {
        var templateName = Ember.getPath(this, 'content.label');
        // return default template if there is no such template 
        return (!Ember.TEMPLATES[templateName]) ? 'default' : templateName;
    }.property('content.label').cacheable(),

    // rerender the view if the template name changes
    _templateNameChanged: function() {
        this.rerender();
    }.observes('templateName')
});

App.CollectionView = Ember.CollectionView.extend({
    itemViewClass: 'App.MyView'
});

Also take a look at the related question: Select view template by model type/object value using Ember.js

Community
  • 1
  • 1
pangratz
  • 15,875
  • 7
  • 50
  • 75
0

Another solution is to use ghempton/ember-layout, see http://jsfiddle.net/pangratz666/XhfYy/:

App.ViewA = Ember.View.extend({
    templateName: "templateA"
});
App.ViewB = Ember.View.extend({
    templateName: "templateB"
});

App.ItemView = Ember.View.extend({
    template: Ember.Handlebars.compile('{{dynamicView content}}')
});

App.CollectionView = Ember.CollectionView.extend({
    itemViewClass: 'App.ItemView'
});

App.controller = Ember.ArrayProxy.create({
    content: [App.ViewA.create(), App.ViewB.create()]
});​
pangratz
  • 15,875
  • 7
  • 50
  • 75
0

In case you also need mutable view class you can use following tooling:

listview.hbs

 {{each item in list itemViewClass=view.Item}}

listview.js

import Ember from 'ember';
import { mutableView } from 'utils/mutable-view';

export default Ember.View.extend({

  Item: mutableView('content.type', function (type, container) {
    if (type === 'type_a') {
      return container.lookupFactory('view:item-a-view');
    }
    if (type === 'type_b') {
      return container.lookupFactory('view:item-b-view');
    }
  }),
});

and finally the utility method mutableView of mutable-view.js

import Ember from 'ember';

var mutableViewTemplate = Ember.Handlebars.compile('{{view view.DynamicView content=view.content}}');

export var mutableView = function(observes, viewSelector) {
  return Ember.View.extend({

    template: mutableViewTemplate,

    __dynamicViewCache: {},

    DynamicView: Ember.computed(observes, function () {
      var view;
      var cache = this.get('__dynamicViewCache');
      var modificator = this.get(observes);

      view = cache[modificator];
      if (view) {
        return view;
      }

      view = viewSelector(modificator, this.get('container'));
      if (view) {
        cache[modificator] = view;
        return view;
      }

      throw new Error(`Cannot determine view class for '${modificator}' of '${observes} '`);
    })
  });
};
Jan Míšek
  • 1,647
  • 1
  • 16
  • 22