AngularJs - annuler l'événement de changement de route

Comment annuler un changement d'itinéraire à AngularJs?

mon code actuel est

$rootScope.$on("$routeChangeStart", function (event, next, current) {

// do some validation checks
if(validation checks fails){

    console.log("validation failed");

    window.history.back(); // Cancel Route Change and stay on current page  

}
});

avec ceci même si la validation échoue angulaire tire le modèle suivant et les données associées et puis passe immédiatement de nouveau à la vue/route précédente. Je ne veux pas qu'angular tire le prochain modèle et les données si la validation échoue, idéalement il ne devrait pas y avoir de fenêtre.histoire.arrière.)( J'ai même essayé l'événement.preventDefault (), mais pas de l'utiliser.

86
demandé sur R Arun 2013-05-02 21:31:25

8 réponses

au lieu de $routeChangeStart utiliser $locationChangeStart

Voici la discussion à ce sujet par les gars d'angularjs: https://github.com/angular/angular.js/issues/2109

Edit 3/6/2018 vous pouvez le trouver dans les documents: https://docs.angularjs.org/api/ng/service / $lieu#event - $locationChangeStart

exemple:

$scope.$on('$locationChangeStart', function(event, next, current) {
    if ($scope.form.$invalid) {
       event.preventDefault();
    }
});
179
répondu Mathew Berg 2018-03-06 14:30:20

un échantillon de code plus complet, en utilisant $locationChangeStart

// assuming you have a module called app, with a 
angular.module('app')
  .controller(
    'MyRootController',
    function($scope, $location, $rootScope, $log) {
      // your controller initialization here ...
      $rootScope.$on("$locationChangeStart", function(event, next, current) { 
        $log.info("location changing to:" + next); 
      });
    }
  );

Je ne suis pas complètement content de l'accrocher dans mon contrôleur root (contrôleur de haut niveau). Si il y a un meilleur modèle, j'aimerais savoir. Je suis nouveau à l'angle: -)

38
répondu Shyam Habarakada 2015-06-16 16:34:35

une solution est de diffuser un événement "non autorisé", et de le saisir dans le but principal de changer de lieu. Je pense que ce n'est pas la meilleure solution, mais ça a fonctionné pour moi:

myApp.run(['$rootScope', 'LoginService',
    function ($rootScope, LoginService) {
        $rootScope.$on('$routeChangeStart', function (event, next, current) {
            var authorizedRoles = next.data ? next.data.authorizedRoles : null;
            if (LoginService.isAuthenticated()) {
                if (!LoginService.isAuthorized(authorizedRoles)) {
                    $rootScope.$broadcast('notAuthorized');
                }
            }
        });
    }
]);

et dans mon contrôleur principal:

    $scope.$on('notAuthorized', function(){
        $location.path('/forbidden');
    });

Note: il y a une discussion sur ce problème sur site angulaire, pas encore résolu: https://github.com/angular/angular.js/pull/4192

EDIT:

pour répondre au commentaire, voici plus d'informations sur les travaux de LoginService. Il contient 3 fonctions:

  1. login () (nom trompeur) faire une demande au serveur pour obtenir des informations sur l'utilisateur (précédemment) connecté. Il y a une autre page de connexion qui remplit simplement l'état utilisateur courant dans le serveur (en utilisant SpringSecurity framework). Mes Services Web ne sont pas vraiment apatrides, mais j'ai préféré laisser cette célèbre cadre Gérer ma sécurité .
  2. isAuthenticated() il suffit de chercher si la Session du client est rempli avec des données, ce qui signifie qu'il a été authentifié avant (*)
  3. isAuthorized() a traité des droits d'accès (hors de la portée de cette rubrique).

(*) Ma Session est remplie lorsque le changement d'itinéraire. J'ai remplacé alors la méthode when () pour remplir la session vide.

voici le code :

services.factory('LoginService', ['$http', 'Session', '$q',
function($http, Session, $q){
    return {
        login: function () {
            var defer = $q.defer();
            $http({method: 'GET', url: restBaseUrl + '/currentUser'})
                .success(function (data) {
                    defer.resolve(data);
                });
            return defer.promise;
        },
        isAuthenticated: function () {
            return !!Session.userLogin;
        },
        isAuthorized: function (authorizedRoles) {
            if (!angular.isArray(authorizedRoles)) {
                authorizedRoles = [authorizedRoles];
            }

            return (this.isAuthenticated() &&  authorizedRoles.indexOf(Session.userRole) !== -1);
        }
    };
}]);

myApp.service('Session', ['$rootScope',
    this.create = function (userId,userLogin, userRole, userMail, userName, userLastName, userLanguage) {
        //User info
        this.userId = userId;
        this.userLogin = userLogin;
        this.userRole = userRole;
        this.userMail = userMail;
        this.userName = userName;
        this.userLastName = userLastName;
        this.userLanguage = userLanguage;
    };

    this.destroy = function () {
        this.userId = null;
        this.userLogin = null;
        this.userRole = null;
        this.userMail = null;
        this.userName = null;
        this.userLastName = null;
        this.userLanguage = null;
        sessionStorage.clear();
    };

    return this;
}]);

myApp.config(['$routeProvider', 'USER_ROLES', function ($routeProvider, USER_ROLES) {
    $routeProvider.accessWhen = function (path, route) {
        if (route.resolve == null) {
            route.resolve = {
                user: ['LoginService','Session',function (LoginService, Session) {
                    if (!LoginService.isAuthenticated())
                        return LoginService.login().then(function (data) {
                            Session.create(data.id, data.login, data.role, data.email, data.firstName, data.lastName, data.language);
                            return data;
                        });
                }]
            }
        } else {
            for (key in route.resolve) {
                var func = route.resolve[key];
                route.resolve[key] = ['LoginService','Session','$injector',function (LoginService, Session, $injector) {
                    if (!LoginService.isAuthenticated())
                        return LoginService.login().then(function (data) {
                            Session.create(data.id, data.login, data.role, data.email, data.firstName, data.lastName, data.language);
                            return func(Session, $injector);
                        });
                    else
                        return func(Session, $injector);
                }];
            }
        }
    return $routeProvider.when(path, route);
    };

    //use accessWhen instead of when
    $routeProvider.
        accessWhen('/home', {
            templateUrl: 'partials/dashboard.html',
            controller: 'DashboardCtrl',
            data: {authorizedRoles: [USER_ROLES.superAdmin, USER_ROLES.admin, USER_ROLES.system, USER_ROLES.user]},
            resolve: {nextEvents: function (Session, $injector) {
                $http = $injector.get('$http');
                return $http.get(actionBaseUrl + '/devices/nextEvents', {
                    params: {
                        userId: Session.userId, batch: {rows: 5, page: 1}
                    },
                    isArray: true}).then(function success(response) {
                    return response.data;
                });
            }
        }
    })
    ...
    .otherwise({
        redirectTo: '/home'
    });
}]);
11
répondu Asterius 2014-11-17 12:58:05

pour quiconque trébuchant sur cette question est une vieille, (au moins dans l'angle 1.4) vous pouvez faire ceci:

 .run(function($rootScope, authenticationService) {
        $rootScope.$on('$routeChangeStart', function (event, next) {
            if (next.require == undefined) return

            var require = next.require
            var authorized = authenticationService.satisfy(require);

            if (!authorized) {
                $rootScope.error = "Not authorized!"
                event.preventDefault()
            }
        })
      })
4
répondu Ákos Vandra 2015-10-16 07:36:59

C'est ma solution et ça marche pour moi mais je ne sais pas si je suis sur la bonne voie car je suis nouveau dans les technologies web.

var app = angular.module("app", ['ngRoute', 'ngCookies']);
app.run(function($rootScope, $location, $cookieStore){
$rootScope.$on('$routeChangeStart', function(event, route){
    if (route.mustBeLoggedOn && angular.isUndefined($cookieStore.get("user"))) {
        // reload the login route
        jError(
             'You must be logged on to visit this page',
             {
               autoHide : true,
               TimeShown : 3000,
               HorizontalPosition : 'right',
               VerticalPosition : 'top',
               onCompleted : function(){ 
               window.location = '#/signIn';
                 window.setTimeout(function(){

                 }, 3000)
             }
        });
    }
  });
});

app.config(function($routeProvider){
$routeProvider
    .when("/signIn",{
        controller: "SignInController",
        templateUrl: "partials/signIn.html",
        mustBeLoggedOn: false
});
1
répondu Alexandrakis alexandros 2014-11-15 23:20:49

dans le cas où vous avez besoin d'arrêter la route de changer dans l'événement $routeChangeStart (i.e. vous voulez effectuer une certaine opération basée sur la route suivante ), injecter $route et à l'intérieur $routeChangeStart appel:

$route.reload()
0
répondu mrt 2013-10-11 16:08:32

j'ai trouvé celui-ci pertinent

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

myApp.run(function($rootScope) {
    $rootScope.$on("$locationChangeStart", function(event, next, current) { 
        // handle route changes  
$rootScope.error = "Not authorized!"
                event.preventDefault()   
    });
});

mon post peut aider quelqu'un dans le futur.

0
répondu Monojit Sarkar 2017-05-10 20:32:50
var app=angular
    .module('myapp', [])
    .controller('myctrl', function($rootScope) {
        $rootScope.$on("locationChangeStart", function(event, next, current) {
        if (!confirm("location changing to:" + next)) { 
            event.preventDefault();
        }
    })
});
-1
répondu Macle Studio 2017-09-14 08:11:51