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 followin
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",{});
}
};
}
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
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.
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});
}
});
});