Reputation: 7478
In my application, I've got an ApplicationAdapter
whose ajaxError
method is customized. Within that method, I'd like to be able to transition to a given route. How can I do this?
App.ApplicationAdapter = DS.RESTAdapter.extend({
ajaxError: function(jqXHR) {
var error = this._super(jqXHR);
if (jqXHR) {
switch(jqXHR.status) {
// [...]
case 401:
// How can I transitionTo('login') here?
}
// [...]
}
}
});
Upvotes: 3
Views: 1730
Reputation: 19128
Instead of transition in the adapter, isn't a good pratice IMHO, you can return an instance of Error
and handle it in the error
action of the current route:
App.UnauthorizedError // create a custom Error class
App.ApplicationAdapter = DS.RESTAdapter.extend({
ajaxError: function(jqXHR) {
var defaultAjaxError = this._super(jqXHR);
if (jqXHR) {
switch(jqXHR.status) {
case 401:
return new App.UnauthorizedError()
}
}
return defaultAjaxError;
}
});
App.IndexRoute = Ember.Route.extend({
model: function() {
return this.store.find('person');
},
actions: {
error: function(reason) {
// all errors will be propagated to here, we check the instance to handle the UnauthorizedError
if (reason instanceof App.UnauthorizedError) {
this.transitionTo('login')
}
}
}
});
If you want to use this for all routes, you can put the unauthorized transition in the ApplicationRoute
. Because the ApplicationRoute is the parent of all routes, and not handled actions, or actions that return true, will bubble to the parent routes.
App.ApplicationRoute = Ember.Route.extend({
actions: {
error: function(reason) {
if (reason instanceof App.UnauthorizedError) {
this.transitionTo('login')
}
}
}
});
App.BarRoute = Ember.Route.extend({
actions: {
error: function(reason) {
// handle errors of bar route
// bubble to application route
return true;
}
}
});
This is a fiddle with this sample http://jsfiddle.net/SkCH5/
Upvotes: 9
Reputation: 47367
Throw the error and allow the error hook on the route to catch it and transition from there. Additionally you can make a mixin with this logic and add the mixin to all of your routes.
Machty has additional information in his gist talking about the new router: https://gist.github.com/machty/5647589
App.AuthenticatedRoute = Ember.Route.extend({
beforeModel: function(transition) {
if (!authTokenPresent) {
return RSVP.reject();
// Could also just throw an error here too...
// it'll do the same thing as returning a rejecting promise.
// Note that we could put the redirecting `transitionTo`
// in here, but it's a better pattern to put this logic
// into `error` so that errors with resolving the model
// (say, the server tells us the auth token expired)
// can also get handled by the same redirect-to-login logic.
}
},
error: function(reason, transition) {
// This hook will be called for any errors / rejected promises
// from any of the other hooks or provided transitionTo promises.
// Redirect to `login` but save the attempted Transition
var loginController = this.controllerFor('login')
loginController.set('afterLoginTransition', transition);
this.transitionTo('login');
}
});
Upvotes: 0