Closed michalc closed 10 years ago
I'm not sure I understand what this is adding to the current API. State transitions are already promise-based, and failures already receive an Error
object with a reason message.
Ah... in that case my second example might not be adding anything, if it's already possible.
However, I think my first use-case/point still might be useful. $state.go is promise-based, but then you have an event-based API to configure the different cases of success/error, which (at least appear to be) synchronous in nature, and don't seem to have a built-in way to defer the route change, or to reject it later. So I'm wondering if something like the following could be possible to define:
'stateChangeStart': function(stateChangeDetails) {
// Say if the user definitely isn't authorised
return $q.reject('No authorisation');
// Or maybe show a login form, which still then allows the route change to fail later
return $modal.show('login');
// Or even redirect to another route
return $state.go('newroute');
},
'stageChangeError': function(rejection) {
// Maybe show global error page?
return $state.go('error');
}
I agree this would be useful. The use case I have in mind is similar to @michalc's.
I want to configure a listener or interceptor to check whether an "authenticate" flag has been set on the target state. If the flag is set, the interceptor checks whether the user is logged in. If the user is not logged in locally, a request is made to the server. If the server responds with a 401, an $http interceptor displays a login form. Once the user has logged in successfully, the chain of promises is resolved and the target state is entered.
Currently this can be achieved by adding a resolve function to each state requiring authentication, but I think it would be good if this could be made easier and more declarative (e.g. with a flag, as above).
I can't see a way to do this with the events which already exist:
module.run(function($rootScope, auth) {
$rootScope.$on('$stateChangeStart', function(event, current, previous) {
if (!current.authenticate) return;
// auth.getUser() may make a request to the server and returns a promise.
auth.getUser().then(function() {
// proceed to "current". (oh, we're already there.)
}).catch(function() {
// stay at "previous". (oops, too late...)
});
});
});
Alternatively, maybe this can be achieved by adding a "private" resolve function dynamically in a builder decorator if the flag is set? I haven't tried that yet, but it sounds a bit dirty.
We are kind of already talking about this over here: https://github.com/angular-ui/ui-router/issues/618#issuecomment-30869009.
I'd say this is a dupe. Please read that post (at least from that comment) and then add your thoughts there.
I think it would be useful to be able to add promise-based interceptors for route/stage changes, just like http interceptors. The current setup of using events seems just a little bit limited for anything but simple situations. Use cases:
I feel there are likely others that I haven't thought of.