我有一个ContainerView
可以交换其他视图。我使用另一个ContainerView
作为内容。在我将其换出后,尝试交换嵌套的ContainerView
会导致错误:Uncaught Error: assertion failed: calling set on destroyed object
。
这是小提琴: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();
答案 0 :(得分:2)
问题是,当您在select1
的{{1}}方法中创建扩展select2
的类时,您正在实例化ContainerView
和widget
。
更改此代码:
App.RangeField
到此:
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'),
...
}
时都会创建新的子视图,而不是重新使用第一次从DOM中删除它们时销毁的相同视图。