AngularJS - Need some combination of $routeChangeStart and $locationChangeStart

后端 未结 4 1738
夕颜
夕颜 2020-12-23 10:46

My problem is actually very similar to the one found here:

AngularJs - cancel route change event

In short, I\'m using $routeChangeStart and trying to change

相关标签:
4条回答
  • 2020-12-23 10:59

    Nice answer Marius, put me on the right track. I'm doing something like this for access control. This works however...

      var resolver = function(route, routeEvent) {
      return {
        load: function($q) {
          deferred = $q.defer();
          if (routeEvent!=3) { // eventually will be a list of routeEvents that the logged-in user is not allowed to visit read from a db table configured by admin
            deferred = $q.defer();
            deferred.resolve();
            return deferred.promise;
          } else { // fire $routeChangeError
            alert("You don't have permissions to access this.");
            deferred.reject(route);
            return deferred.promise;
          }
        }
      }
    }
    
      var jsonRoutes = [
    
        {'route' : '/logout', 'templateUrl': 'partials/login.html',   'controller' : 'LoginCtrl', 'routeEvent' : 1 },
        {'route' : '/orders', 'templateUrl': 'partials/orders.html',   'controller': 'OrderListCtrl', 'routeEvent' : 2 },
        {'route' : '/products', 'templateUrl': 'partials/products.html',   'controller': 'ProductListCtrl', 'routeEvent' : 3 },
    
    ...
    
    ];
    
    
    // somewhere on successful login code add in the dynamic routes
    
    angular.forEach(jsonRoutes, function(r) {
                    $route.routes[r.route] = {templateUrl: r.templateUrl, controller: r.controller, routeEvent: r.routeEvent, resolve: resolver(r.route, r.routeEvent)};
                      });
    
    
    // got some static routes too which don't have access control - user has to login right?
    
      config(['$routeProvider', function($routeProvider) {
    
    
      $routeProvider.
        when('/error',  {templateUrl: 'partials/error.html',   controller : ErrorCtrl,  routeEvent : 1 }).
        when('/login',  {templateUrl: 'partials/login.html',   controller : LoginCtrl, routeEvent : 1 }).
        when('/home',  {templateUrl: 'partials/home.html',   controller : HomeCtrl, routeEvent : 1 }).
        when('/logout', {templateUrl: 'partials/login.html',   controller : LoginCtrl, routeEvent : 1 }).
        otherwise( {redirectTo: '/error'} );   
    

    When the /orders route is clicked the promise is rejected (with a pop-up, could be modal dialog) and the route isn't followed.

    Hope this helps someone.

    0 讨论(0)
  • 2020-12-23 11:12

    I faced the same situation myself and my solution was aligned with what the OP intended to do.

    I use the $locationChangeStart event and the $route service. By accessing $route.routes, I get a hold of all route objects defined with $routeProvider.

    .run(function($rootScope, $route, $location) {
      $rootScope.$on('$locationChangeStart', function(ev, next, current) {
        // We need the path component of `next`. We can either process `next` and 
        // spit out its path component, or simply use $location.path(). I go with
        // the latter.
        var nextPath = $location.path();
        var nextRoute = $route.routes[nextPath]
    
        console.log(nextRoute.access); // There you go!
      });
    })
    

    To parse the path component out of an absolute URL:

    var urlParsingNode = document.createElement('a');
    urlParsingNode.href = next;  // say, next = 'http://www.abc.com/foo?name=joe
    console.log(urlParsingNode.pathname)  // returns "/foo"
    
    0 讨论(0)
  • 2020-12-23 11:12

    Since version 1.3.0 you can actually use the newly introduced preventDefault-method. With that you can cancel the current route change and then apply your own custom redirect as shown in this github-issue:

    
    $rootScope.$on("$routeChangeStart", function (event, next, current) {
        if (next.access) {
          event.preventDefault();
          $rootScope.$evalAsync(function() {
            $location.path('/login');
          });
        }
    });
    

    I implemented this method in my own project and it works perfectly. Hope it helps anyone else who stumbles across it.

    0 讨论(0)
  • 2020-12-23 11:18

    One approach that comes to mind is trying to use the resolve parameter for this:

    var resolver = function(access) {
      return {
        load: function($q) {
          if (access) { // fire $routeChangeSuccess
            var deferred = $q.defer();
            deferred.resolve();
            return deferred.promise;
          } else { // fire $routeChangeError
            return $q.reject("/login");
          }
        }
      }
    }
    
    $routeProvider.
      when('/login', { controller: 'LoginCtrl', templateUrl: '/app/partial/login.html', resolve: resolver(false)}).
      when('/home', { controller: 'HomeCtrl', templateUrl: '/app/partial/home.html', resolve: resolver(true)}).
      otherwise({ redirectTo: '/login' });
    

    Please note that I haven't tested the code above but I'm doing similar stuff in my projects.

    0 讨论(0)
提交回复
热议问题