Redirection vers un certain itinéraire en fonction de la condition

493

J'écris une petite application AngularJS qui a une vue de connexion et une vue principale, configurées comme suit:

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

Mon LoginController vérifie la combinaison utilisateur / passe et définit une propriété sur $ rootScope reflétant ceci:

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.";
    }
}

Tout fonctionne, mais si j'y accède, http://localhost/#/mainje finis par contourner l'écran de connexion. Je voulais écrire quelque chose comme "chaque fois que l'itinéraire change, si $ rootScope.loggedUser est nul, puis rediriger vers / login"

...

... attendre. Puis-je écouter les changements d'itinéraire en quelque sorte? Je vais quand même poster cette question et continuer à chercher.

st.never
la source
3
Juste pour clarifier: bien que de nombreuses solutions ci-dessous fonctionnent bien, j'ai récemment été plus enclin à accepter la réponse de @ Oran ci-dessous - c'est-à-dire que le serveur réponde avec un code 401 lorsqu'on lui demande une URL sensible et utilise ces informations pour contrôler la "boîte de connexion" sur le client. (Cependant, le jury est toujours sur le bit "mettre en file d'attente les demandes refusées et les réémettre plus tard", du moins pour moi :))
st.never

Réponses:

510

Après avoir plongé dans la documentation et le code source, je pense que je l'ai fait fonctionner. Peut-être que cela sera utile pour quelqu'un d'autre?

J'ai ajouté ce qui suit à la configuration de mon module:

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" );
        }
      }         
    });
 })

La seule chose qui semble étrange est que j'ai dû tester le nom partiel ( login.html) parce que l'objet "suivant" Route n'avait pas d'URL ou autre chose. Peut-être y a-t-il une meilleure façon?

st.never
la source
13
Cool man, merci de partager votre solution. Une chose à noter: dans la version actuelle, il est « à côté $ route.templateUrl. »
doubledriscoll
5
Si vous regardez les demandes réseau dans l'inspecteur Chrome, l'itinéraire qui est redirigé (car l'utilisateur n'est pas connecté) est toujours appelé et une réponse est envoyée au navigateur, puis le chemin redirigé '/ login' est appelé. Cette méthode n'est donc pas utile car les utilisateurs non connectés peuvent voir la réponse pour un itinéraire auquel ils ne devraient pas avoir accès.
sonicboom
34
Utilisez $ locationChangeStart au lieu de $ routeChangeStart pour empêcher la route d'être appelée et permettre aux utilisateurs non authentifiés de visualiser le contenu auquel ils ne devraient pas avoir accès.
sonicboom
17
N'oubliez pas qu'il s'agit du client. Il devrait également y avoir une barrière côté serveur.
Neikos
2
@sonicboom $ locationChangeStart n'a pas de sens si toutes les routes ne nécessitent pas d'authentification, avec $ routeChangeStart, vous pouvez avoir des métadonnées sur les objets route, comme s'il est authentifié ou non ou quels rôles sont requis pour cette route. Votre serveur doit gérer le fait de ne pas afficher le contenu non authentifié et AngularJS ne commencera le traitement qu'après le changement de route de toute façon, donc rien ne devrait être affiché.
Chris Nicola
93

Voici peut-être une solution plus élégante et flexible avec une propriété de configuration «résoudre» et des «promesses» permettant un éventuel chargement de données sur le routage et des règles de routage en fonction des données.

Vous spécifiez une fonction dans «résoudre» dans la configuration de routage et dans la fonction charger et vérifier les données, faire toutes les redirections. Si vous devez charger des données, vous retournez une promesse, si vous devez faire une redirection - rejetez la promesse avant cela. Tous les détails peuvent être trouvés sur les pages de documentation $ routerProvider et $ q .

'use strict';

var app = angular.module('app', [])
    .config(['$routeProvider', function($routeProvider) {
        $routeProvider
            .when('/', {
                templateUrl: "login.html",
                controller: LoginController
            })
            .when('/private', {
                templateUrl: "private.html",
                controller: PrivateController,
                resolve: {
                    factory: checkRouting
                }
            })
            .when('/private/anotherpage', {
                templateUrl:"another-private.html",
                controller: AnotherPriveController,
                resolve: {
                    factory: checkRouting
                }
            })
            .otherwise({ redirectTo: '/' });
    }]);

var checkRouting= function ($q, $rootScope, $location) {
    if ($rootScope.userProfile) {
        return true;
    } else {
        var deferred = $q.defer();
        $http.post("/loadUserProfile", { userToken: "blah" })
            .success(function (response) {
                $rootScope.userProfile = response.userProfile;
                deferred.resolve(true);
            })
            .error(function () {
                deferred.reject();
                $location.path("/");
             });
        return deferred.promise;
    }
};

Pour les russophones, il y a un article sur habr " Вариант условного раутинга в AngularJS ".

Nikolay Popov
la source
1
Pourquoi la fonction checkRouting est-elle mappée en usine? Est-il important de savoir à quoi il est mappé?
honkskillet
@honkskillet: Dans les documents angulaires $ routeProvider: "factory - {string | function}: Si string alors c'est un alias pour un service. Sinon si function, alors il est injecté et la valeur de retour est traitée comme la dépendance. Si le Le résultat est une promesse, il est résolu avant que sa valeur ne soit injectée dans le contrôleur. N'oubliez pas que ngRoute. $ routeParams fera toujours référence à la route précédente dans ces fonctions de résolution. Utilisez $ route.current.params pour accéder aux nouveaux paramètres de route, au lieu." Également à partir de documents sur la résolution: "Si l'une des promesses est rejetée, l'événement $ routeChangeError est déclenché."
Tim Perry du
Si ui.routerest utilisé, utilisez à la $stateProvider place de $routeProvider.
TRiNE
61

J'ai essayé de faire de même. Je suis venu avec une autre solution plus simple après avoir travaillé avec un collègue. J'ai installé une montre $location.path(). Ça fait l'affaire. Je commence tout juste à apprendre AngularJS et je trouve cela plus propre et plus lisible.

$scope.$watch(function() { return $location.path(); }, function(newValue, oldValue){  
    if ($scope.loggedIn == false && newValue != '/login'){  
            $location.path('/login');  
    }  
});
user1807337
la source
Cela semble très intéressant. Avez-vous pu publier un exemple quelque part?
kyleroche
3
Où installez-vous la montre?
freakTheMighty
3
@freakTheMighty Vous devez configurer la montre dans votre fonction mainCtrl, où ng-controller est réglé sur mainCtrl. par exemple <body ng-controller = "mainCtrl">
user1807337
5
Je pense qu'il est juste que si un vote négatif est donné, il devrait avoir un commentaire motivé. Il vous sera utile comme outil d'apprentissage.
user1807337
37

Une autre manière de mettre en œuvre la redirection de connexion consiste à utiliser les événements et les intercepteurs comme décrit ici . L'article décrit certains avantages supplémentaires tels que la détection d'une connexion requise, la mise en file d'attente des demandes et leur relecture une fois la connexion réussie.

Vous pouvez essayer une démonstration de travail ici et voir la source de démonstration ici .

Oran Dennison
la source
3
Pourriez-vous mettre à jour cette réponse pour inclure les informations pertinentes des liens? De cette façon, il continuera à être utile aux visiteurs même si les liens descendent.
josliber
34

1. Définissez l'utilisateur actuel global.

Dans votre service d'authentification, définissez l'utilisateur actuellement authentifié sur la portée racine.

// AuthService.js

  // auth successful
  $rootScope.user = user

2. Définissez la fonction d'authentification sur chaque itinéraire protégé.

// AdminController.js

.config(function ($routeProvider) {
  $routeProvider.when('/admin', {
    controller: 'AdminController',
    auth: function (user) {
      return user && user.isAdmin
    }
  })
})

3. Vérifiez l'authentification à chaque changement d'itinéraire.

// index.js

.run(function ($rootScope, $location) {
  $rootScope.$on('$routeChangeStart', function (ev, next, curr) {
    if (next.$$route) {
      var user = $rootScope.user
      var auth = next.$$route.auth
      if (auth && !auth(user)) { $location.path('/') }
    }
  })
})

Vous pouvez également définir des autorisations sur l'objet utilisateur et attribuer à chaque route une autorisation, puis vérifier l'autorisation dans le rappel d'événement.

AJcodez
la source
@malcolmhall yup, c'est opt-in et vous voulez vous désinscrire. Ajoutez plutôt un booléen "public" aux routes publiques comme la page de connexion et redirigezif (!user && !next.$$route.public)
AJcodez
Quelqu'un pourrait-il m'expliquer next.$$route? Je ne trouve rien dans les documents angulaires qui décrivent les arguments donnent à un $routeChangeStartévénement, mais je suppose nextet currsont une sorte d'objets de localisation? Le $$routebit est difficile à google.
skagedal
2
Je vois maintenant que la $$routepropriété est une variable privée d'Angular. Vous ne devriez pas vous y fier, voir par exemple: stackoverflow.com/a/19338518/1132101 - si vous le faites, votre code pourrait se casser lorsque Angular change.
skagedal
2
J'ai trouvé un moyen d'accéder à la route sans accès à une propriété privée ou d' avoir à boucle à travers $route.routesde construire une liste (comme dans la réponse de @ thataustin): obtenir le chemin pour l'emplacement avec next.originalPathet l' utiliser pour l' indice $route.routes: var auth = $route.routes[next.originalPath].
skagedal
Quant à répondre à ma question d'il y a trois commentaires sur les arguments qui sont donnés à l'événement - ils semblent en effet être sans papiers, voir cette question qui arrive également à référencer cette question SO: github.com/angular/angular.js/issues/ 10994
skagedal
27

Voici comment je l'ai fait, au cas où cela aiderait quelqu'un:

Dans la configuration, j'ai défini un publicAccessattribut sur les quelques routes que je souhaite ouvrir au public (comme la connexion ou l'enregistrement):

$routeProvider
    .when('/', {
        templateUrl: 'views/home.html',
        controller: 'HomeCtrl'
    })
    .when('/login', {
        templateUrl: 'views/login.html',
        controller: 'LoginCtrl',
        publicAccess: true
    })

puis dans un bloc d'exécution, j'ai mis un écouteur sur l' $routeChangeStartévénement qui redirige vers à '/login'moins que l'utilisateur ait accès ou que la route soit accessible au public:

angular.module('myModule').run(function($rootScope, $location, user, $route) {

    var routesOpenToPublic = [];
    angular.forEach($route.routes, function(route, path) {
        // push route onto routesOpenToPublic if it has a truthy publicAccess value
        route.publicAccess && (routesOpenToPublic.push(path));
    });

    $rootScope.$on('$routeChangeStart', function(event, nextLoc, currentLoc) {
        var closedToPublic = (-1 === routesOpenToPublic.indexOf($location.path()));
        if(closedToPublic && !user.isLoggedIn()) {
            $location.path('/login');
        }
    });
})

Vous pouvez évidemment changer la condition de isLoggedInn'importe quoi d'autre ... montrant simplement une autre façon de le faire.

thataustin
la source
et quel est l'utilisateur dans vos arguments de bloc d'exécution? un service?
mohamnag
oui, c'est un service qui s'occupe de vérifier les cookies, etc. pour voir si l'utilisateur est connecté.
thataustin
Vous pouvez accéder à l'itinéraire comme nextLoc.$$route.publicAccessbtw.
AJcodez
Ou utilisez $route.routes[nextLoc.originalPath], qui n'utilise pas de variable privée.
skagedal
1
En fait, vous pouvez simplement vérifier nextLoc && nextLoc.publicAccess!
skagedal
9

Je le fais en utilisant des intercepteurs. J'ai créé un fichier de bibliothèque qui peut être ajouté au fichier index.html. De cette façon, vous aurez une gestion globale des erreurs pour vos appels de service de repos et vous n'aurez pas à vous soucier de toutes les erreurs individuellement. Plus bas, j'ai également collé ma bibliothèque de connexion d'authentification de base. Là, vous pouvez voir que je vérifie également l'erreur 401 et que je redirige vers un autre emplacement. Voir lib / ea-basic-auth-login.js

lib / http-error-handling.js

/**
* @ngdoc overview
* @name http-error-handling
* @description
*
* Module that provides http error handling for apps.
*
* Usage:
* Hook the file in to your index.html: <script src="lib/http-error-handling.js"></script>
* Add <div class="messagesList" app-messages></div> to the index.html at the position you want to
* display the error messages.
*/
(function() {
'use strict';
angular.module('http-error-handling', [])
    .config(function($provide, $httpProvider, $compileProvider) {
        var elementsList = $();

        var showMessage = function(content, cl, time) {
            $('<div/>')
                .addClass(cl)
                .hide()
                .fadeIn('fast')
                .delay(time)
                .fadeOut('fast', function() { $(this).remove(); })
                .appendTo(elementsList)
                .text(content);
        };

        $httpProvider.responseInterceptors.push(function($timeout, $q) {
            return function(promise) {
                return promise.then(function(successResponse) {
                    if (successResponse.config.method.toUpperCase() != 'GET')
                        showMessage('Success', 'http-success-message', 5000);
                    return successResponse;

                }, function(errorResponse) {
                    switch (errorResponse.status) {
                        case 400:
                            showMessage(errorResponse.data.message, 'http-error-message', 6000);
                                }
                            }
                            break;
                        case 401:
                            showMessage('Wrong email or password', 'http-error-message', 6000);
                            break;
                        case 403:
                            showMessage('You don\'t have the right to do this', 'http-error-message', 6000);
                            break;
                        case 500:
                            showMessage('Server internal error: ' + errorResponse.data.message, 'http-error-message', 6000);
                            break;
                        default:
                            showMessage('Error ' + errorResponse.status + ': ' + errorResponse.data.message, 'http-error-message', 6000);
                    }
                    return $q.reject(errorResponse);
                });
            };
        });

        $compileProvider.directive('httpErrorMessages', function() {
            return {
                link: function(scope, element, attrs) {
                    elementsList.push($(element));
                }
            };
        });
    });
})();

css / http-error-handling.css

.http-error-message {
    background-color: #fbbcb1;
    border: 1px #e92d0c solid;
    font-size: 12px;
    font-family: arial;
    padding: 10px;
    width: 702px;
    margin-bottom: 1px;
}

.http-error-validation-message {
    background-color: #fbbcb1;
    border: 1px #e92d0c solid;
    font-size: 12px;
    font-family: arial;
    padding: 10px;
    width: 702px;
    margin-bottom: 1px;
}

http-success-message {
    background-color: #adfa9e;
    border: 1px #25ae09 solid;
    font-size: 12px;
    font-family: arial;
    padding: 10px;
    width: 702px;
    margin-bottom: 1px;
}

index.html

<!doctype html>
<html lang="en" ng-app="cc">
    <head>
        <meta charset="utf-8">
        <title>yourapp</title>
        <link rel="stylesheet" href="css/http-error-handling.css"/>
    </head>
    <body>

<!-- Display top tab menu -->
<ul class="menu">
  <li><a href="#/user">Users</a></li>
  <li><a href="#/vendor">Vendors</a></li>
  <li><logout-link/></li>
</ul>

<!-- Display errors -->
<div class="http-error-messages" http-error-messages></div>

<!-- Display partial pages -->
<div ng-view></div>

<!-- Include all the js files. In production use min.js should be used -->
<script src="lib/angular114/angular.js"></script>
<script src="lib/angular114/angular-resource.js"></script>
<script src="lib/http-error-handling.js"></script>
<script src="js/app.js"></script>
<script src="js/services.js"></script>
<script src="js/controllers.js"></script>
<script src="js/filters.js"></script>

lib / ea-basic-auth-login.js

Presque la même chose peut être faite pour la connexion. Ici, vous avez la réponse à la redirection ($ location.path ("/ login")).

/**
* @ngdoc overview
* @name ea-basic-auth-login
* @description
*
* Module that provides http basic authentication for apps.
*
* Usage:
* Hook the file in to your index.html: <script src="lib/ea-basic-auth-login.js">  </script>
* Place <ea-login-form/> tag in to your html login page
* Place <ea-logout-link/> tag in to your html page where the user has to click to logout
*/
(function() {
'use strict';
angular.module('ea-basic-auth-login', ['ea-base64-login'])
    .config(['$httpProvider', function ($httpProvider) {
        var ea_basic_auth_login_interceptor = ['$location', '$q', function($location, $q) {
            function success(response) {
                return response;
            }

            function error(response) {
                if(response.status === 401) {
                    $location.path('/login');
                    return $q.reject(response);
                }
                else {
                    return $q.reject(response);
                }
            }

            return function(promise) {
                return promise.then(success, error);
            }
        }];
        $httpProvider.responseInterceptors.push(ea_basic_auth_login_interceptor);
    }])
    .controller('EALoginCtrl', ['$scope','$http','$location','EABase64Login', function($scope, $http, $location, EABase64Login) {
        $scope.login = function() {
            $http.defaults.headers.common['Authorization'] = 'Basic ' + EABase64Login.encode($scope.email + ':' + $scope.password);
            $location.path("/user");
        };

        $scope.logout = function() {
            $http.defaults.headers.common['Authorization'] = undefined;
            $location.path("/login");
        };
    }])
    .directive('eaLoginForm', [function() {
        return {
            restrict:   'E',
            template:   '<div id="ea_login_container" ng-controller="EALoginCtrl">' +
                        '<form id="ea_login_form" name="ea_login_form" novalidate>' +
                        '<input id="ea_login_email_field" class="ea_login_field" type="text" name="email" ng-model="email" placeholder="E-Mail"/>' +
                        '<br/>' +
                        '<input id="ea_login_password_field" class="ea_login_field" type="password" name="password" ng-model="password" placeholder="Password"/>' +
                        '<br/>' +
                        '<button class="ea_login_button" ng-click="login()">Login</button>' +
                        '</form>' +
                        '</div>',
            replace: true
        };
    }])
    .directive('eaLogoutLink', [function() {
        return {
            restrict: 'E',
            template: '<a id="ea-logout-link" ng-controller="EALoginCtrl" ng-click="logout()">Logout</a>',
            replace: true
        }
    }]);

angular.module('ea-base64-login', []).
    factory('EABase64Login', function() {
        var keyStr = 'ABCDEFGHIJKLMNOP' +
            'QRSTUVWXYZabcdef' +
            'ghijklmnopqrstuv' +
            'wxyz0123456789+/' +
            '=';

        return {
            encode: function (input) {
                var output = "";
                var chr1, chr2, chr3 = "";
                var enc1, enc2, enc3, enc4 = "";
                var i = 0;

                do {
                    chr1 = input.charCodeAt(i++);
                    chr2 = input.charCodeAt(i++);
                    chr3 = input.charCodeAt(i++);

                    enc1 = chr1 >> 2;
                    enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
                    enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
                    enc4 = chr3 & 63;

                    if (isNaN(chr2)) {
                        enc3 = enc4 = 64;
                    } else if (isNaN(chr3)) {
                        enc4 = 64;
                    }

                    output = output +
                        keyStr.charAt(enc1) +
                        keyStr.charAt(enc2) +
                        keyStr.charAt(enc3) +
                        keyStr.charAt(enc4);
                    chr1 = chr2 = chr3 = "";
                    enc1 = enc2 = enc3 = enc4 = "";
                } while (i < input.length);

                return output;
            },

            decode: function (input) {
                var output = "";
                var chr1, chr2, chr3 = "";
                var enc1, enc2, enc3, enc4 = "";
                var i = 0;

                // remove all characters that are not A-Z, a-z, 0-9, +, /, or =
                var base64test = /[^A-Za-z0-9\+\/\=]/g;
                if (base64test.exec(input)) {
                    alert("There were invalid base64 characters in the input text.\n" +
                        "Valid base64 characters are A-Z, a-z, 0-9, '+', '/',and '='\n" +
                        "Expect errors in decoding.");
                }
                input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");

                do {
                    enc1 = keyStr.indexOf(input.charAt(i++));
                    enc2 = keyStr.indexOf(input.charAt(i++));
                    enc3 = keyStr.indexOf(input.charAt(i++));
                    enc4 = keyStr.indexOf(input.charAt(i++));

                    chr1 = (enc1 << 2) | (enc2 >> 4);
                    chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
                    chr3 = ((enc3 & 3) << 6) | enc4;

                    output = output + String.fromCharCode(chr1);

                    if (enc3 != 64) {
                        output = output + String.fromCharCode(chr2);
                    }
                    if (enc4 != 64) {
                        output = output + String.fromCharCode(chr3);
                    }

                    chr1 = chr2 = chr3 = "";
                    enc1 = enc2 = enc3 = enc4 = "";

                } while (i < input.length);

                return output;
            }
        };
    });
})();
Christopher Armstrong
la source
2
Vous devriez vraiment éviter de faire de la manipulation dom dans le JS, sauf si vous êtes dans une directive. Si vous venez de configurer votre logique, puis utilisez ng-class pour appliquer une classe et déclencher une animation CSS, vous vous en remercierez plus tard.
Askdesigners
7

Dans votre fichier app.js:

.run(["$rootScope", "$state", function($rootScope, $state) {

      $rootScope.$on('$locationChangeStart', function(event, next, current) {
        if (!$rootScope.loggedUser == null) {
          $state.go('home');
        }    
      });
}])
Ben Cochrane
la source
4

Il est possible de rediriger vers une autre vue avec angular-ui-router . Pour cela, nous avons la méthode $state.go("target_view"). Par exemple:

 ---- app.js -----

 var app = angular.module('myApp', ['ui.router']);

 app.config(function ($stateProvider, $urlRouterProvider) {

    // Otherwise
    $urlRouterProvider.otherwise("/");

    $stateProvider
            // Index will decide if redirects to Login or Dashboard view
            .state("index", {
                 url: ""
                 controller: 'index_controller'
              })
            .state('dashboard', {
                url: "/dashboard",
                controller: 'dashboard_controller',
                templateUrl: "views/dashboard.html"
              })
            .state('login', {
                url: "/login",
                controller: 'login_controller',
                templateUrl: "views/login.html"
              });
 });

 // Associate the $state variable with $rootScope in order to use it with any controller
 app.run(function ($rootScope, $state, $stateParams) {
        $rootScope.$state = $state;
        $rootScope.$stateParams = $stateParams;
    });

 app.controller('index_controller', function ($scope, $log) {

    /* Check if the user is logged prior to use the next code */

    if (!isLoggedUser) {
        $log.log("user not logged, redirecting to Login view");
        // Redirect to Login view 
        $scope.$state.go("login");
    } else {
        // Redirect to dashboard view 
        $scope.$state.go("dashboard");
    }

 });

----- HTML -----

<!DOCTYPE html>
<html>
    <head>
        <title>My WebSite</title>

        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
        <meta name="description" content="MyContent">
        <meta name="viewport" content="width=device-width, initial-scale=1">

        <script src="js/libs/angular.min.js" type="text/javascript"></script>
        <script src="js/libs/angular-ui-router.min.js" type="text/javascript"></script>
        <script src="js/app.js" type="text/javascript"></script>

    </head>
    <body ng-app="myApp">
        <div ui-view></div>
    </body>
</html>
Jesús Castro
la source
3

Si vous ne souhaitez pas utiliser angular-ui-router, mais souhaitez que vos contrôleurs soient chargés paresseusement via RequireJS, il y a quelques problèmes avec l'événement $routeChangeStartlors de l'utilisation de vos contrôleurs en tant que modules RequireJS (chargés paresseusement).

Vous ne pouvez pas être sûr que le contrôleur sera chargé avant d' $routeChangeStartêtre déclenché - en fait, il ne sera pas chargé. Cela signifie que vous ne pouvez pas accéder aux propriétés de l' nextitinéraire comme localsou $$routeparce qu'elles ne sont pas encore configurées.
Exemple:

app.config(["$routeProvider", function($routeProvider) {
    $routeProvider.when("/foo", {
        controller: "Foo",
        resolve: {
            controller: ["$q", function($q) {
                var deferred = $q.defer();
                require(["path/to/controller/Foo"], function(Foo) {
                    // now controller is loaded
                    deferred.resolve();
                });
                return deferred.promise;
            }]
        }
    });
}]);

app.run(["$rootScope", function($rootScope) {
    $rootScope.$on("$routeChangeStart", function(event, next, current) {
        console.log(next.$$route, next.locals); // undefined, undefined
    });
}]);

Cela signifie que vous ne pouvez pas y vérifier les droits d'accès.

Solution:

Comme le chargement du contrôleur se fait via résoudre, vous pouvez faire de même avec votre contrôle de contrôle d'accès:

app.config(["$routeProvider", function($routeProvider) {
    $routeProvider.when("/foo", {
        controller: "Foo",
        resolve: {
            controller: ["$q", function($q) {
                var deferred = $q.defer();
                require(["path/to/controller/Foo"], function(Foo) {
                    // now controller is loaded
                    deferred.resolve();
                });
                return deferred.promise;
            }],
            access: ["$q", function($q) {
                var deferred = $q.defer();
                if (/* some logic to determine access is granted */) {
                    deferred.resolve();
                } else {
                    deferred.reject("You have no access rights to go there");
                }
                return deferred.promise;
            }],
        }
    });
}]);

app.run(["$rootScope", function($rootScope) {
    $rootScope.$on("$routeChangeError", function(event, next, current, error) {
        console.log("Error: " + error); // "Error: You have no access rights to go there"
    });
}]);

Notez ici qu'au lieu d'utiliser l'événement que $routeChangeStartj'utilise$routeChangeError

Ivan Hušnjak
la source
-4
    $routeProvider
 .when('/main' , {templateUrl: 'partials/main.html',  controller: MainController})
 .when('/login', {templateUrl: 'partials/login.html', controller: LoginController}).
 .when('/login', {templateUrl: 'partials/index.html', controller: IndexController})
 .otherwise({redirectTo: '/index'});
Dixit Hasija
la source
Il s'agit d'une configuration de route de base ... Où vérifions-nous toute condition avant de rediriger vers les routes configurées ..?
TJ