问题
I'm writing a single page application in Angular, specifically angular.dart, but I'm assuming this question still applies to AngularJS.
Take for example the following routes:
/login - Expects nobody to be logged in. If someone is authenticated but not registered, redirect to "register" route, if they are registered, redirect to the "home" route.
/register - Expects an authenticated user who hasn't finished the registration process. If not authenticated, redirect to login. If is authenticated, redirect to home.
/home - Expects an authenticated and registered user. If not authenticated, redirect to "login" route, if not registered, redirect to "register" route.
I've done quite a bit of searching but cannot find a built-in or idiomatic way to check to make sure that certain preconditions are met before loading the controller associated with a particular route, and to redirect appropriately when these preconditions are not met.
Any help would be greatly appreciated!
回答1:
Angular.Dart and Angular.JS routing frameworks are very/fundamentally different. Angular.Dart is using a third party routing framework (https://github.com/dart-lang/route/tree/experimental_hierarchical) and only implements angular specific features like ng-view
and ways to bind routes to templates via ViewFactory
.
So your question really falls into the route_hierarchical
package domain. Currently you can veto users attempt to navigate away from a route, but I guess what you want the ability to veto user entering a route depending on if the user is logged in or not. Unfortunately this is not yet supported, but is planned.
What you could try in the meantime is creating a custom viewFactory wrapper.
class RecipesRouteInitializer implements RouteInitializer {
void init(Router router, ViewFactory view) {
router
..addRoute(
name: 'login',
path: '/login',
enter: authView(router, view('login.html'), NOT_AUTH))
..addRoute(
name: 'register',
path: '/register',
enter: authView(router, view('register.html'), AUTH_NO_REG))
..addRoute(
name: 'home',
path: '/home',
enter: authView(router, view('home.html'), AUTH_AND_REG));
}
authView(Router router, ngView, mode) {
return (RouteEvent e) {
if (mode == AUTH_AND_REG) {
if (!authService.isAuth) {
router.go('login', {});
return;
}
if (!authService.isReg) {
router.go('register', {});
return;
}
} else if (mode == AUTH_NO_REG) {
if (!authService.isAuth) {
router.go('login', {});
return;
}
if (authService.isReg) {
router.go('home', {});
return;
}
} else if (mode == NOT_AUTH) {
if (authService.isAuth) {
router.go('register', {});
return;
}
}
ngView(e);
};
}
}
DISCLAMER: this is just an idea... might totally not work.
回答2:
Well, I made a thing in Dart which is close to one of the previous solutions which don't really work. The main point is that in the RouteEventHandler
, you need to call the RouteEventHandler
of the view.
..addRoute(
name: 'userAdd',
path: '/userAdd',
enter: checkAuthentication(router,view,'view/addUser.html'))
..addRoute(
name: 'login',
path: '/login',
enter: view('view/login.html'));
}
RouteEventHandler checkAuthentication(Router router,ViewFactory view, String location){
return (RouteEvent e) {
if(_authenticationService.isAuthenticated()){
view(location)(e);
}else{
router.go("login",{});
}
};
}
回答3:
Note: this applies to AngularJS only, leaving this up in case someone using JS needs it.
Take a look at the resolve
property in $routeProvider. You can return a promise which will determine whether the route change should be accepted or not.
From the docs:
If any of these dependencies are promises, the router will wait for them all to be resolved or one to be rejected before the controller is instantiated. If all the promises are resolved successfully, the values of the resolved promises are injected and $routeChangeSuccess event is fired. If any of the promises are rejected the $routeChangeError event is fired.
There's also a video about it and the route lifecycle on egghead.io here
回答4:
I know that following solution is not applicable to Angular.Dart, but still is worth to mention solution for ui-router:
https://github.com/angular-ui/ui-router/wiki/Frequently-Asked-Questions#how-to-create-rules-to-prevent-access-to-a-state
app.config(function($stateProvider) {
$stateProvider.state('privatePage', {
data: {
rule: function(user) {
// ...
}
});
});
app.run(function($rootScope, $state, $currentUser) {
$rootScope.$on('$stateChangeStart', function(e, to) {
if (!angular.isFunction(to.data.rule)) return;
var result = to.data.rule($currentUser);
if (result && result.to) {
e.preventDefault();
// Optionally set option.notify to false if you don't want
// to retrigger another $stateChangeStart event
$state.go(result.to, result.params, {notify: false});
}
});
});
来源:https://stackoverflow.com/questions/20429997/verifying-route-preconditions-prior-to-loading-controller