Search code examples
angularjsngroute

Redirecting to a certain route based on condition


I'm writing a small AngularJS app that has a login view and a main view, configured like so:

$routeProvider
 .when('/main' , {templateUrl: 'partials/main.html',  controller: MainController})
 .when('/login', {templateUrl: 'partials/login.html', controller: LoginController})
 .otherwise({redirectTo: '/login'});

My LoginController checks the user/pass combination and sets a property on the $rootScope reflecting this:

function LoginController($scope, $location, $rootScope) {
 $scope.attemptLogin = function() {
   if ( $scope.username == $scope.password ) { // test
        $rootScope.loggedUser = $scope.username;
        $location.path( "/main" );
    } else {
        $scope.loginError = "Invalid user/pass.";
    }
}

Everything works, but if I access http://localhost/#/main I end up bypassing the login screen. I wanted to write something like "whenever the route changes, if $rootScope.loggedUser is null then redirect to /login"

...

... wait. Can I listen to route changes somehow? I'll post this question anyway and keep looking.


Solution

  • After some diving through some documentation and source code, I think I got it working. Perhaps this will be useful for someone else?

    I added the following to my module configuration:

    angular.module(...)
     .config( ['$routeProvider', function($routeProvider) {...}] )
     .run( function($rootScope, $location) {
    
        // register listener to watch route changes
        $rootScope.$on( "$routeChangeStart", function(event, next, current) {
          if ( $rootScope.loggedUser == null ) {
            // no logged user, we should be going to #login
            if ( next.templateUrl != "partials/login.html" ) {
              // not going to #login, we should redirect now
              $location.path( "/login" );
            }
          }         
        });
     })
    

    The one thing that seems odd is that I had to test the partial name (login.html) because the "next" Route object did not have a url or something else. Maybe there's a better way?