I am having problems updating the template property on an Ember view when it is a computed property.
Ember compiles the template correctly when the view first loads
That's not how you should set the template. The template should not return a compiled template but rather act as a compiled template. In your code you're trying to set the template itself as a computed property and you're compiling two possible templates to it conditionally. IMHO you should compile a template with a binding to a computed property that evaluates a text based on your toggle property, like this:
App = Em.Application.create();
App.MyView = Em.View.extend({
template: Em.Handlebars.compile('toggle is {{toggleState}}'),
toggle: true,
toggleState: function(){
if (this.get('toggle')) {
return 'set to \'true\'';
} else {
return 'set to \'false\'';
}
}.property('toggle')
});
theView = App.MyView.create();
theView.append('body');
Ember.run.later(function() {
console.log('later');
theView.set('toggle',false);
}, 2000);
See fiddle here
This will only change what needs to be change, so you don't have to re-compile a template.
EDIT:
I've made some modifications to the fiddle (You can see it here).
What I am doing, instead of assigning the template
property directly, I'm compiling the templates to Ember.TEMPLATES
collection before creating the app (I'm assuming you'll do something like this in prod anyway), and I'm changing your computed property to return the name of the template to be used depending on the condition (in your case content.type
), and I'm binding the templateName
property that computed property. Once the template changes, you have to rerender
your view. The code can be improved, but I'll paste it here to demonstrate the solution:
(function() {
Em.TEMPLATES["one"] = Em.Handlebars.compile('{{view.content.data}}');
Em.TEMPLATES["two"] = Em.Handlebars.compile('{{view.content.data}}
');
})();
App = Em.Application.create();
App.MyView = Em.CollectionView.extend({
content: [
Em.Object.create({type: 1, data:"Item type 1 is a link"}),
Em.Object.create({type: 2, data:"Item type 2 is a header"})
],
itemViewClass: Em.View.extend({
templateNameBinding: 'currentTypeName',
currentTypeName: function() {
if (this.get('content.type') == 1) {
return "one";
} else if (this.get('content.type') == 2) {
return "two";
}
}.property('content.type'),
templateNameObserver: function() {
this.rerender();
}.observes('templateName')
})
});
// ... rest of the code...
Like I said, this code can be improved... hope this helps