I have an Ember list and an edit form. Each time the selected item of the list changes the edit form discards any changes and loads new model.
My problem is that there is no way to discard changes because the deactivate event does NOT fire.
For example going from url/favs/123/edit
to url/favs/456/edit
deactivate (and exit) event does NOT fire. So there is no way to properly discard any changes.
Here is the part of my code I am referring to:
App.Router.map(function() {
this.resource('favs', { path: '/favs' }, function() {
this.route('new');
this.route('edit', { path: ':fav_id/edit' })
});
});
[...]
App.FavsEditRoute = Ember.Route.extend({
deactivate: function() {
var model = this.get('currentModel');
if(model && model.get('isDirty')) {
model.get('transaction').rollback();
}
},
model: function(params) {
return App.Fav.find(params.fav_id);
},
});
I'd recommend using the willTransition route action. It currently appears to be advertised as the solution in the Ember Guide:
https://guides.emberjs.com/release/routing/preventing-and-retrying-transitions/
Aside from being in the public API, this approach has the advantage that you can prompt the user to confirm if they actually want to abandon the change, nullifying the transition if they say no.
For example:
App.FavsEditRoute = Ember.Route.extend({
...
actions: {
willTransition: function(transition) {
controller = this.controllerFor('fav');
if (controller.get('isDirty') &&
!confirm("Are you sure you want to abandon progress?")) {
transition.abort();
return false;
} else {
controller.get("content").rollback();
return true;
}
}
}
});
The deactivate hook is just executed when the route is left completely. Therefore i would suggest to overwrite the contextDidChange function of your Route. Here is an excerpt from the Ember Source:
Ember.Route = Ember.Object.extend({
/**
@private
Called when the context is changed by router.js.
*/
contextDidChange: function() {
this.currentModel = this.context;
}
});
I would suggest to do this:
App.FavsEditRoute = Ember.Route.extend({
deactivate: function() {
this.doRollback();
},
contextDidChange: function() {
this.doRollback();
this._super();
},
doRollback: function(){
var model = this.get('currentModel');
if(model && model.get('isDirty')) {
model.get('transaction').rollback();
}
}
});
In Ember 2.2 the correct code (in route) is:
actions: {
saveScene: function (scene) {
var _that = this;
scene.save().then(function (response) {
// on saveScene action, go to list route
_that.transitionTo('scenes');
});
},
willTransition: function (transition) {
// on transition, if model has unsaved changes, revert them
var model = this.controller.get('model');
if (model && model.get('hasDirtyAttributes')) {
model.rollbackAttributes();
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With