web-dev-qa-db-fra.com

AngularJS: angular-ui-router est toujours redirigé vers $ urlRouterProvider.otherwise

J'essaie de créer un SPA où vous devez être connecté pour accéder à presque tout. Alors, naturellement, l'écran par défaut que vous voyez est l'écran de connexion. Cependant, après la connexion d'un utilisateur, quel que soit le ui-sref, ui-router redirige vers la page de connexion (même lorsque l'utilisateur est authentifié). Voici mon code ui-router:

(function () {
'use strict';
angular
    .module('app', ['ui.router', 'satellizer'])
    .config(function ($stateProvider, $urlRouterProvider, $authProvider, $httpProvider, $provide) {
  
        $httpProvider.interceptors.Push(['$q', '$injector', function($q, $injector){
            return {
                responseError: function (rejection) {
                    var $state = $injector.get('$state');
                    var rejectionReasons = ['token_not_provided', 'token_expired', 'token_absent', 'token_invalid'];
                    angular.forEach(rejectionReasons, function (value, key) {
                        if (rejection.data.error === value) {
                            localStorage.removeItem('user');
                            $state.go('auth');
                        }
                    });

                    return $q.reject(rejection);
                },
                response: function(response) {
                    var authorization = response.headers('authorization');
                    if(authorization !== null) {
                        authorization = authorization.substr(7).trim();
                        //console.log(authorization);
                        var $auth = $injector.get('$auth');
                        $auth.setToken(authorization);
                    }
                    return response;
                }
            }
        }]);

        $authProvider.loginUrl = 'mingdaograder/api/authenticate';

        $stateProvider
            .state('users', {
                url: '/users',
                templateUrl: 'views/userView.html',
                controller: 'UserController as user'
            })
            .state('subjects', {
                url: '/users/:user_id/subjects',
                templateUrl: 'views/subjectsView.html',
                controller: 'SubjectsCtrl as subjectsCtrl'
            })
            .state('subject', {
                url: '/users/:user_id/subjects/:subject_id',
                templateUrl: 'views/subjectView.html',
                controller: 'SubjectCtrl as subjectCtrl'
            })
            .state('auth', {
                url: '/auth',
                templateUrl: 'views/authView.html',
                controller: 'AuthController as auth'
            });
            //.state('otherwise', {
            //    url: '*path',
            //    templateUrl: 'views/authView.html',
            //    controller: 'AuthController as auth'
            //});

            //$urlRouterProvider.otherwise('/auth');
            $urlRouterProvider.otherwise(function($injector, $location) {
                console.log("Could not find " + $location);
                $location.path('/auth');
            });
    })
    .run(function ($rootScope, $state, $log) {
        $rootScope.$on('$stateChangeStart', function (event, toState) {
                console.log(toState.name);
            var user = JSON.parse(localStorage.getItem('user'));
            if (user) {
                $rootScope.authenticated = true;
                $rootScope.currentUser = user;
            }
        }
        );
    }
);
})();

À chaque fois que j'essaie d'utiliser $ state.go (n'importe quel nom d'état ici} _) ou même de taper l'adresse dans la barre d'adresse, je suis toujours redirigé vers l'état auth. Sur la console, le message est "Impossible de trouver http: // localhost/#/ " pour chaque itinéraire. Je peux taper http: // localhost/#/users/5/sujets et je reçois le même message.

Voici l'un de mes contrôleurs faisant une redirection:

(function () {
    'use strict';

    angular
        .module('app')
        .controller('AuthController', AuthController);

    function AuthController($auth, $state, $http, $rootScope, $log) {
        var vm = this;

        vm.loginError = false;
        vm.loginErrorText;

        vm.login = function () {
            var credentials = {
                username: vm.username,
                password: vm.password
            };

            $auth.login(credentials).then(function () {
                return $http.get('api/authenticate/user');
            }, function (error) {
                vm.loginError = true;
                vm.loginErrorText = error.data.error;
            }).then(function (response) {
                var user = JSON.stringify(response.data.user);
                localStorage.setItem('user', user);
                $rootScope.authenticated = true;
                $rootScope.currentUser = response.data.user;

                //$log.info('From AuthCtrl: ' + $rootScope.currentUser.id);
                $state.go('subjects', {user_id:$rootScope.currentUser.id});
            });
        }
    }
})();

Des idées que je fais mal? Merci beaucoup pour votre temps.

Update : D'accord, je n'ai pas trouvé de solution, mais je pense avoir trouvé une cause possible. Cela ne semble se produire que pour les routes avec paramètres. Par exemple, si je passe à l'état users _ dont le chemin est/users, il n'y a pas de redirection. Cependant, si je passe à l'état sujets dont le chemin est/users /: id_utilisateur/sujets, la redirection est effective. C'est comme si le service de correspondance d'URL ne pouvait pas reconnaître que/utilisateurs/5/sujets correspond/utilisateurs /: utilisateur_id/sujets, donc redirige. Des idées comment travailler autour de ceci?

7
Brent Parker

J'ai trouvé que je n'avais pas de '/' au début de mon URL d'état initial. Chaque fois que je naviguais dans cet état, le "/" manquant semblait le pousser dans l'étatProvider.

state1: 'opportunity'
state1Url : '/opportunity/' <== added initial forward slash to make it work.

state2: 'opportunity.create'
state2Url : 'create/'
9
sarin

Le premier chemin à reconnaître sera celui sélectionné comme emplacement actuel. Cela signifie que l'ordre de vos définitions d'itinéraire est d'une importance cruciale. Dans votre cas, vous n'avez qu'une seule définition de route otherwise complète et attrayante. Comme toutes les routes correspondent à cette dernière, toutes les routes sont dirigées vers votre page de connexion, ignorant toute autre définition de route que vous pourriez avoir, y compris toutes vos définitions d'état stateProvider.

Une solution consiste à supprimer la définition de la route urlRouterProvider et à utiliser la syntaxe *path fournie par ui-router pour créer un autre état otherwise (qui doit être défini en dernier pour les mêmes raisons que celles indiquées ci-dessus).

Par conséquent, votre code pourrait ressembler à ceci:

$stateProvider
    .state('auth', {
        url: '/auth',
        templateUrl: 'views/authView.html',
        controller: 'AuthController as auth'
    })
    .state('users', {
        url: '/users',
        templateUrl: 'views/userView.html',
        controller: 'UserController as user'
    })
    .state('subjects', {
        url: '/users/:user_id/subjects',
        templateUrl: 'views/subjectsView.html',
        controller: 'SubjectsCtrl as subjectsCtrl'
    })
    .state('subject', {
        url: '/users/:user_id/subjects/:subject_id',
        templateUrl: 'views/subjectView.html',
        controller: 'SubjectCtrl as subjectCtrl'
    })
    .state("otherwise", {
        url: "*path",
        templateUrl: 'views/authView.html',
        controller: 'AuthController as auth'
    });
1
biofractal