21
locationChangeStart $

Mein Problem mit dem einen hier eigentlich sehr ähnlich ist:

AngularJs - cancel route change event

Kurz gesagt, ich $ routeChangeStart bin mit und versuchen, den Strom zu ändern Route mit $ location. Wenn ich das mache, zeigt mir die Konsole, dass die Originalseite noch geladen ist und schnell von der neuen Seite überschrieben wird.

Als Lösung wurde $ locationChangeStart anstelle von $ routeChangeStart verwendet, was die zusätzliche Umleitung verhindern sollte. Leider verwende ich zusätzliche Daten im $ routeprovider, auf die ich zugreifen muss, während ich die Route ändere (ich verwende es, um Seitenbeschränkungen zu verfolgen). Hier ist ein Beispiel ...

$routeProvider. 
    when('/login', { controller: 'LoginCtrl', templateUrl: '/app/partial/login.html', access: false}). 
    when('/home', { controller: 'HomeCtrl', templateUrl: '/app/partial/home.html', access: true}). 
    otherwise({ redirectTo: '/login' }); 


$rootScope.$on('$routeChangeStart', function(event, next, current) { 
    if(next.access){ 
     //Do Stuff 
    } 
    else{ 
     $location.path("/login"); 
     //This will load the current route first (ie: '/home'), and then 
     //redirect the user to the correct 'login' route. 
    } 
}); 

Mit $ routeChangeStart, kann ich die „next“ und „Strom“ Parameter (siehe AngularJS - $route) als Objekte meine ‚Zugang‘ Werte abzurufen. Mit $ locationChangeStart geben diese beiden Parameter URL-Strings zurück, keine Objekte. Es scheint also keine Möglichkeit zu geben, meine "Zugriffs" -Werte abzurufen.

Gibt es eine Möglichkeit, die Redirect-Stop-Power von $ locationChangeStart mit der Objektflexibilität von $ routeChangeStart zu kombinieren, um das zu erreichen, was ich brauche?

Antwort

21

Ein Ansatz, der in den Sinn kommt versucht, die Entschlossenheit Parameter für diesen Einsatz:

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

Bitte beachten Sie, dass ich nicht den Code oben getestet haben, aber ich tue ähnliche Sachen in meinen Projekten.

+0

Entschuldigung für die späte Antwort. Wenn etwas für mich funktioniert, neige ich dazu, mich zu freuen und weiterzumachen. Dies endete als eine perfekte Lösung für das, was ich tat.In der Ladefunktion konnte ich Dinge wie '$ http' und '$ location' hinzufügen, um meine Anfragen weiter zu bearbeiten. – ThisLanham

+0

Ich musste meine Ladefunktion eher wie die von Nick http://stackoverflow.com/a/19482187/1449799 aussehen lassen (der Ausschuss funktionierte nicht so wie hier geschrieben) – Michael

+1

'load' Funktion sollte eher so lesen: 'var latent = $ q.defer(); if (Zugriff) {deferred.resolve(); } else {deferred.reject(); $ location.url ('/ login'); } return deferred.promise; ' – Clay

3

Schöne Antwort Marius, setze mich auf die richtige Spur. Ich mache so etwas für die Zugangskontrolle. Dies funktioniert jedoch ...

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

Wenn die/Aufträge Route das Versprechen angeklickt wird, wird zurückgewiesen (mit einem Pop-up, könnte modaler Dialog sein) und die Route nicht gefolgt ist.

Ich hoffe, das hilft jemandem.

+0

irgendeinen Hinweis darauf? – Awena

14

Ich selbst war mit der gleichen Situation konfrontiert und meine Lösung wurde mit dem abgestimmt, was das OP vorhatte.

Ich verwende das $locationChangeStart Ereignis und das $route Service. Wenn ich auf $route.routes zugreife, erhalte ich alle mit $routeProvider definierten Routenobjekte.

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

Um die Pfadkomponente aus einem absoluten URL analysieren:

var urlParsingNode = document.createElement('a'); 
urlParsingNode.href = next; // say, next = 'http://www.abc.com/foo?name=joe 
console.log(urlParsingNode.pathname) // returns "/foo" 
+0

Was ist, wenn es Abfrageparameter in der URL gibt ... Wie identifizieren Sie, welcher Router aufgerufen wird – niran

+0

@niran - Ich habe meine Antwort für Sie aktualisiert. Schau mal. – tamakisquare

+3

Wie funktioniert das für Routen mit Parametern? wie/artikel /: artikelId? – mkhatib

7

Seit Version 1.3.0 Sie tatsächlich den neu eingeführten preventDefault -Methode verwenden können. Damit können Sie die aktuelle Route ändern abbrechen und dann Ihre eigene Anwendung umleiten, wie in diesen github-issue gezeigt:


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

implementiert ich diese Methode in meinem eigenen Projekt und es funktioniert perfekt. Hoffe, es hilft jedem anderen, der darüber stolpert.

Verwandte Themen