How to destroy and recreate a controller object in Ember framework


#1

I am using Ember 2.12, there are two controllers - one for applicant and other for coapplicant for our application flow. When the user decides to delete the coapplicant, I am trying to get rid of its state (that unfortunately lives in the coapplicant controller instead of a separate data object). so i am trying to destroy the controller and then recreate it the next time the page loads.

in the resetController state, I call

this.destroy();

And in the routes/form.js page, in the

setupController(controller,model)

I am checking if the controller is destroyed, i tried to recreate it

if (controller.isDestroyed) {
		Ember.Logger.error('controller is already destroyed');
		this.set('controller',FormEditCoapplicantController.create());
	}
	this._super(...arguments);

but when i do that, I get the error when this._super(…arguments) is called,

Error while processing route: form-edit-coapplicant Assertion Failed: calling set on destroyed object: <account-open@controller:form-edit-coapplicant::ember3345>.model = [object Object] Error: Assertion Failed: calling set on destroyed object: <account-open@controller:form-edit-coapplicant::ember3345>.model = [object Object]
at assert (http://localhost:4200/assets/vendor.js:21056:13)
at Object.assert (http://localhost:4200/assets/vendor.js:32807:34)
at Object.set (http://localhost:4200/assets/vendor.js:37553:22)
at Class.setupController (http://localhost:4200/assets/vendor.js:42366:21)
at Class.setupController (http://localhost:4200/assets/vendor.js:207076:9)
at Class.superWrapper (http://localhost:4200/assets/vendor.js:55946:22)
at Class.setupController (http://localhost:4200/assets/account-open.js:6331:16)
at Class.superWrapper [as setupController] (http://localhost:4200/assets/vendor.js:55946:22)
at Class.setupController (http://localhost:4200/assets/account-open.js:7184:16)
at Class.superWrapper [as setupController] (http://localhost:4200/assets/vendor.js:55946:22)

Is there anything that i missing here.

I don’t want to clear the controller state by manually resetting each field because the logic for that is very complex (there are lots of fields, some are computed properties, some conditionally prefilled/not-prefilled depending on data availability, I am assuming if i can somehow destroy and recreate the controller in this case, i can get the brand new created controller with its state back to original without much manual effort.


#2

.destroy is a hook. It’s not something that you should be calling yourself.

Controllers are singleton that’s managed by the container. You simply cannot destroy them. You’re right that the state needs to be cleared in resetController hook. If you need to clear the model and invoke the model hooks again, use Route#refresh. Note this will trigger a route transition into itself.


#3

thanks for your suggestion @lightblade. But even if i force the model values to be updated, the values in the state related fields that live inside controller directly - won’t get cleared. And there are quite a few of them, around 50. So i will have to clear them all manually via this.setProperties method. I was hoping there was a way where i could say controller.destroy and controller.create - which will recreate the controller there by re-initializing the state of the controller by resetting all fields to their default values. If that’s not possible, i guess i have to reset those fields individually.

The suggestion about resetController - that’s just a method, where the controller will need to get reset. its not a shortcut to reset the controller automagically - did i get this right ?

I see the documentation

import Route from '@ember/routing/route';

export default Route.extend({
 resetController(controller, isExiting, transition) {
if (isExiting && transition.targetName !== 'error') {
  controller.set('page', 1);
  }
  }
 });

it just provides a lifecycle hook which lets me decide when to reset the controller fields, but it doesn’t provide a shortcut to reset the controller itself by recreating the class itself (even if its a singleton, it shouldn’t be impossible to destroy and recreate it.


#4

There are no way to destroy and recreate in the controller in the way that you described.

That does raises the question though. If theses values are transient, shouldn’t they belong in a component? A component does get teardown and recreated every time you render it.