Ember view template as a computed property

前端 未结 1 1307
青春惊慌失措
青春惊慌失措 2021-01-03 16:57

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

1条回答
  •  北海茫月
    2021-01-03 17:17

    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

    0 讨论(0)
提交回复
热议问题