2013-02-18 51 views
4

我有一個ContainerView可以交換其他視圖。我使用另一個ContainerView作爲內容。試圖交換嵌套的ContainerView,在我將其交換後導致錯誤:Uncaught Error: assertion failed: calling set on destroyed object將ContainerView交換爲另一個ContainerView會導致銷燬視圖

這裏的小提琴:http://jsfiddle.net/hekevintran/bFSKD/

爲了使錯誤發生,請單擊「其他表」,然後單擊「第一單」。

我認爲這個錯誤是因爲從ContainerViews中刪除的視圖被銷燬,並且沒有重新創建嵌套的ContainerView的子視圖。什麼是解決這個例子的正確方法?

模板:

<script type="text/x-handlebars" data-template-name="box"> 
<div> 
    {{#each forms}} 
     <button {{action "selectForm" this }}>{{this.name}}</button> 
    {{/each}} 
    {{view container}} 
</div> 
</script> 

<script type="text/x-handlebars" data-template-name="form"> 
    <form> 
     {{#each fields}} 
      <div> 
       {{this.label}}: {{view this.widget}} 
      </div> 
     {{/each}} 
    </form> 
</script> 

的JavaScript:

App = Ember.Application.create({}); 

App.BoxController = Ember.Object.extend({ 
    initialForm: null, 
    currentForm: null, 
    init: function() { 
     var form = this.get('initialForm'); 
     this.set('currentForm', form); 
     this.get('container').set('currentView', form.get('view').create()); 
    }, 
    forms: [], 
    container: function() { 
     return Ember.ContainerView.create({ 
      boxController: this, 
      controllerBinding: 'boxController.currentForm' 
     }) 
    }.property(), 
    selectForm: function (form) { 
     this.set('currentForm', form); 
     this.get('container').set('currentView', form.get('view').create()); 
    } 
}); 

App.Field = Ember.Object.extend({ 
    value: null, 
    widgetBaseClass: Ember.TextField, 
    widget: function() { 
     return this.get('widgetBaseClass').extend({ 
      field: this, 
      valueBinding: 'field.value' 
     }); 
    }.property('widgetBaseClass') 
}); 

App.RangeField = App.Field.extend({ 
    widget: function() { 
     var field = this; 
     return Ember.ContainerView.extend({ 
      childViews: [field.get('select1').create(), field.get('select2').create()] 
     }); 
    }.property('select1', 'select2'), 
    fromValue: null, 
    toValue: null, 
    value: function() { 
     return [this.get('fromValue.value'), this.get('toValue.value')]; 
    }.property('fromValue', 'toValue'), 
    choices: [ 
     '1', 
     '2', 
     '3', 
     '4' 
    ], 
    remainingChoices: function() { 
     var fromValue = this.get('fromValue'); 
     if (fromValue) { 
      var choices = this.get('choices'); 
      var index = choices.indexOf(fromValue); 
      return choices.slice(index + 1); 
     } 
     return []; 
    }.property('fromValue', 'choices'), 
    select1: function() { 
     return Ember.Select.extend({ 
      field: this, 
      valueBinding: 'field.fromValue', 
      contentBinding: 'field.choices' 
     }); 
    }.property(), 
    select2: function() { 
     return Ember.Select.extend({ 
      field: this, 
      valueBinding: 'field.toValue', 
      contentBinding: 'field.remainingChoices', 
      contentHasChangedOnce: false, 
      contentChanged: function() { 
       // Set the initial value only once 
       if (! this.get('contentHasChangedOnce')) { 
        this.set('contentHasChangedOnce', true); 
        this.set('value', this.get('content')[0]); 
       } 

       // Reset the value if the chosen value is no longer 
       // available 
       if (! this.get('content').contains(this.get('value'))) { 
        this.set('value', this.get('content')[0]); 
       } 
      }.observes('content') 
     }); 
    }.property() 
}); 

App.Form = Ember.Object.extend({ 
    fieldNames: [], 
    fields: function() { 
     var that = this; 
     var out = []; 
     _.each(this.get('fieldNames'), function (fieldName) { 
      out.pushObject(that.get(fieldName)); 
     }); 
     return out; 
    }.property('fieldNames') 
}); 

aForm = App.Form.create({ 
    name: 'First Form', 
    fieldNames: [ 
     'a', 
     'b' 
    ], 
    a: App.Field.create({label: 'A'}), 
    b: App.RangeField.create({label: 'B'}), 
    view: Ember.View.extend({ 
     templateName: 'form' 
    }) 
}); 

var boxController = App.BoxController.create({ 
    initialForm: aForm, 
    forms: [ 
     aForm, 
     Ember.Object.create({ 
      name: 'Other Form', 
      view: Ember.View.extend({ 
       template: Ember.Handlebars.compile('Foobar') 
      }) 
     }) 
    ] 
}); 

var boxView = Ember.View.create({ 
    templateName: 'box', 
    controller: boxController 
}); 

boxView.append(); 

回答

2

的問題是,你是實例select1select2當您創建的App.RangeFieldwidget方法內部延伸ContainerView類。

更改此代碼:

App.RangeField = App.Field.extend({ 
    widget: function() { 
     var field = this; 
     return Ember.ContainerView.extend({ 
      childViews: [field.get('select1').create(), field.get('select2').create()] 
     }); 
    }.property('select1', 'select2'), 
    ... 
} 

這樣:

App.RangeField = App.Field.extend({ 
    widget: function() { 
     var field = this; 
     return Ember.ContainerView.extend({ 
      init: function() { 
       this.set('childViews', [field.get('select1').create(), field.get('select2').create()]); 
       this._super(); 
      } 
     }); 
    }.property('select1', 'select2'), 
... 
} 

現在你創建新的子每次實例widget而不是時間觀再次使用它被毀第一相同的兩個觀點你從DOM中刪除它們。

相關問題