programing

AngularJs - 경로 변경 이벤트 취소

minxs 2023. 3. 7. 22:01
반응형

AngularJs - 경로 변경 이벤트 취소

AngularJs에서 루트 변경 이벤트를 취소하려면 어떻게 해야 합니까?

현재 코드는

$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  

}
});

이를 통해 검증에 실패하더라도 Angular는 다음 템플릿과 관련 데이터를 꺼낸 다음 즉시 이전 뷰/루트로 다시 전환합니다.검증에 실패했을 경우 Angular가 다음 템플릿과 데이터를 풀하지 않도록 합니다.이상적으로는 창이 없습니다.history.back 명령어event.proventDefault()까지 시도했지만 소용이 없었습니다.

대신$routeChangeStart사용하다$locationChangeStart

angularjs guys https://github.com/angular/angular.js/issues/2109 에서의 토론입니다.

2018년 3월 6일 편집 다음 문서에서 찾을 수 있습니다.https://docs.angularjs.org/api/ng/service/$location#event-$locationChangeStart

예:

$scope.$on('$locationChangeStart', function(event, next, current) {
    if ($scope.form.$invalid) {
       event.preventDefault();
    }
});

보다 완전한 코드 샘플,$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); 
      });
    }
  );

루트 컨트롤러(최상위 컨트롤러)에 접속하는 것은 그다지 만족스럽지 않습니다.더 좋은 패턴이 있다면 알고 싶어요.각도 :-)는 처음입니다.

해결책은 'Not'을 브로드캐스트하는 것입니다.Authorized' 이벤트를 메인 스코프에서 포착하여 위치를 변경합니다.최선의 해결책은 아니라고 생각합니다만, 저는 효과가 있었습니다.

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');
                }
            }
        });
    }
]);

메인 컨트롤러:

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

주의: 이 문제는 아직 해결되지 않은 각 사이트에서 논의되고 있습니다.https://github.com/angular/angular.js/pull/4192

편집:

코멘트에 응답하기 위해서, Login Service 의 동작에 관한 상세 정보를 다음에 나타냅니다.다음 3가지 기능이 있습니다.

  1. login() (이름은 오해의 소지가 있다)서버에 대한 요구를 실시해, (이전에 기록된) 유저에 관한 정보를 취득합니다.(Spring Security 프레임워크를 사용하여) 서버의 현재 사용자 상태를 채우는 다른 로그인 페이지가 있습니다.내 웹 서비스는 진정한 상태 비저장 기능은 아니지만, 나는 그 유명한 프레임워크가 내 보안을 처리하도록 하는 것을 선호한다.
  2. isAuthenticated()는 클라이언트의 세션이 데이터로 채워져 있는지 검색하기만 하면 됩니다.이는 세션이 (*) 이전에 인증되었음을 의미합니다.
  3. is Authorized()는 액세스 권한을 처리했습니다(이 토픽의 범위외).

(*) 루트가 변경되면 My Session이 입력됩니다.when() 메서드를 덮어쓰고 비어 있을 때 세션을 채웁니다.

코드는 다음과 같습니다.

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'
    });
}]);

이것에 걸려든 사람은, (적어도 1.4 의 각도에서는) 다음과 같이 할 수 있습니다.

 .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()
            }
        })
      })

이것은 나의 솔루션이고, 나에게도 효과가 있지만, 나는 웹 테크놀로지에 익숙하지 않기 때문에 내가 올바른 길을 가고 있는지 모르겠다.

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

난 이게 관련이 있다는 걸 알았어

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

내 게시물이 미래에 누군가를 도울지도 모른다.

var app=angular
    .module('myapp', [])
    .controller('myctrl', function($rootScope) {
        $rootScope.$on("locationChangeStart", function(event, next, current) {
        if (!confirm("location changing to:" + next)) { 
            event.preventDefault();
        }
    })
});

의 가 있는 $routeChangeStart이벤트(, 다음 경로에 따라 일부 작업을 수행하려는 경우), 주입$route 내부 및 and$routeChangeStart 삭제:

$route.reload()

제 경우 $routeChangeStart를 사용하여 루트 해결을 지연시키고 싶습니다.루트 해결이 시작되기 전에 로드해야 하는 Something Service(네, 채팅 어플리케이션)가 있기 때문에 기다리는 것이 좋습니다.해킹을 찾은 것 같아해결이 거부반응을 반환하면 루트의 해결이 에러가 됩니다.해상도 설정을 해제하고 나중에 복구합니다.

    var rejectingResolve = {
        cancel: function ($q){
            // this will cancel $routeChangeStart
            return $q.reject();
        }
    }
    
    $rootScope.$on("$routeChangeStart", function(event, args, otherArgs) {
        var route = args.$$route,
            originalResolve = route.resolve;
    
        if ( ! SomethingService.isLoaded() ){

            SomethingService.load().then(function(){
                // fix previously destroyed route configuration
                route.resolve = originalResolve;
                
                $location.search("ts", new Date().getTime());
                // for redirections
                $location.replace();
            });

            // This doesn't work with $routeChangeStart: 
            // we need the following hack
            event.preventDefault();
            
            // This is an hack! 
            // We destroy route configuration, 
            // we fix it back when SomethingService.isLoaded
            route.resolve = rejectingResolve;
        } 
    });

언급URL : https://stackoverflow.com/questions/16344223/angularjs-cancel-route-change-event

반응형