Moving a ContainerView to and from another ContainerView results in broken views

I have a ContainerView that swaps other views. I am using another ContainerView as content. An attempt to exchange in a nested ContainerView after I changed it leads to an error: Uncaught Error: assertion failed: calling set on destroyed object .

Here's the fiddle: http://jsfiddle.net/hekevintran/bFSKD/

To make a mistake, click on β€œOther Form,” and then click β€œFirst Form.”

I think the error is due to the fact that views deleted from ContainerViews are destroyed, and child views of nested ContainerView not recreated. What is the correct way to fix this example?

Templates:

 <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(); 
+4
source share
1 answer

The problem is that you create select1 and select2 when you create a class that extends ContainerView inside the widget method of App.RangeField .

Change this code:

 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'), ... } 

Now you create new child views every time you create a widget instance instead of reusing the same two views that were destroyed the first time you deleted them from the DOM.

+2
source

All Articles