Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cancel route and redirect to other route without displaying the original content in AngularJS

I want to check an http services to see if a user is authenticated and if it has permission to see the certain page (controller) in AngularJS 1.2.0rc1.

I have this scenario: User A wants to visit http://www.example.com/content. Now this content should not be accessible when he or she is not authenticated. If the user is not authenticated, they should be redirected to http://www.example.com/login.

Now I managed to do this, but I see the rendered html of the content page briefly. I don't want this. How do I redirect to the login page, without rendering the content page?

I register my routes as such:

$routeProvider.when('/login', route.resolve('Login', false))
$routeProvider.when('/content', route.resolve('Content', true))

Now I've tried this:

$rootScope.$on('$routeChangeStart', function (event, route) {
    if (route.requiresLogin) {
        $http.get('/api/user/loggedin/').then(function (response) {
            if (response !== 'true') {
                $location.path('/login');
            }
        });
    }
});

Which works, but I still see the content of the html of the other page (content) flashing.

I've read that here that you can also try to change the resolve functionality when the route is resolved:

    var resolve = function (baseName, requiresLogin) {
    var routeDef = {};
    var dependencies = [routeConfig.getControllersDirectory() + baseName + 'Controller.js'];

    routeDef.templateUrl = routeConfig.getViewsDirectory() + baseName.toLowerCase() + '.html';
    routeDef.controller = baseName + 'Controller';
    routeDef.requiresLogin = requiresLogin;
    routeDef.resolve = {
        load: ['$q', '$rootScope', '$http', '$location', function ($q, $rootScope, $http, $location) {
            console.log(requiresLogin);
            if (requiresLogin) {
                return checkLoggedIn($q, $rootScope, $http, $location);
            } else {
                return resolveDependencies($q, $rootScope, dependencies);
            }
        }]
    };

    return routeDef;
}

But here the page is also displayed briefly.

Hope that you can help me out.

like image 899
Aldentev Avatar asked Aug 15 '13 15:08

Aldentev


1 Answers

The first answer should work, but to do it using $q I would use defer.resolve() or defer.reject("rejection_reason") then I would listen for a $routeChangeError in a top-level controller that is bound to an an element outside of the ng-view that the routeProvider manages.

So in your HTML, something like:

<body ng-app="app" ng-controller="DocumentCtrl">
  <div ng-view>
  </div>
</body>

Then that route of yours would be defined something like:

when('/home', {
  templateUrl: templateUrl blah,
  controller: baseName + 'Controller',
  resolve: {
    load: function($q, MY_USER_SERVICE){
      var defer = $q.defer();
      if(~MY USER LOGGED_IN LOGIC RETURNS TRUE~){
        defer.resolve();
      } else {
        defer.reject("not_logged_in");
      }
      return defer.promise;

    }
  }
}).

Then my DocumentCtrl controller would contain:

$scope.$on("$routeChangeError", function(evt,current,previous,rejection){
  if(rejection == "not_logged_in"){
    //DO SOMETHING
  } else {
    //OR DO SOMETHING ELSE
  }
});

I'm running the above and there's no flash of any views that shouldn't be loaded.

like image 56
Ade Avatar answered Nov 16 '22 04:11

Ade