Umleiten zu einer bestimmten Route basierend auf der Bedingung

493

Ich schreibe eine kleine AngularJS-App mit einer Anmeldeansicht und einer Hauptansicht, die wie folgt konfiguriert sind:

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

Mein LoginController überprüft die Benutzer / Pass-Kombination und legt eine Eigenschaft für $ rootScope fest, die Folgendes widerspiegelt:

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

Alles funktioniert, aber wenn ich darauf zugreife http://localhost/#/main, umgehe ich den Anmeldebildschirm. Ich wollte etwas schreiben wie "Wenn sich die Route ändert, wenn $ rootScope.loggedUser null ist, leiten Sie zu / login um".

...

... warten. Kann ich mir Routenänderungen irgendwie anhören? Ich werde diese Frage trotzdem posten und weiter suchen.

st.never
quelle
3
Nur zur Verdeutlichung: Während viele der folgenden Lösungen gut funktionieren, war ich in letzter Zeit eher geneigt, die unten stehende Antwort von @ Oran zu akzeptieren. Das heißt, der Server muss mit einem 401-Code antworten, wenn er nach einer vertraulichen URL gefragt wird, und diese Informationen zur Steuerung verwenden das "Login-Feld" auf dem Client. (Allerdings ist die Jury immer noch nicht mit dem Bit "
Abgelehnte

Antworten:

510

Nach einigem Durchstöbern der Dokumentation und des Quellcodes habe ich es geschafft. Vielleicht ist dies für jemand anderen nützlich?

Ich habe meiner Modulkonfiguration Folgendes hinzugefügt:

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

Das eine, was seltsam erscheint, ist, dass ich den Teilnamen ( login.html) testen musste, weil das "nächste" Route-Objekt keine URL oder etwas anderes hatte. Vielleicht gibt es einen besseren Weg?

st.never
quelle
13
Cooler Mann, danke, dass du deine Lösung geteilt hast. Eine Sache zu beachten: In der aktuellen Version ist es „nächster $ route.templateUrl.“
doubledriscoll
5
Wenn Sie sich die Netzwerkanforderungen im Chrome Inspector ansehen, wird die umgeleitete Route (da der Benutzer nicht angemeldet ist) weiterhin aufgerufen und eine Antwort an den Browser gesendet. Anschließend wird der umgeleitete Pfad '/ login' aufgerufen. Diese Methode ist also nicht gut, da nicht angemeldete Benutzer die Antwort für eine Route sehen können, auf die sie keinen Zugriff haben sollten.
Sonicboom
34
Verwenden Sie $ locationChangeStart anstelle von $ routeChangeStart, um zu verhindern, dass die Route aufgerufen wird und nicht authentifizierte Benutzer Inhalte anzeigen, auf die sie keinen Zugriff haben sollten.
Sonicboom
17
Denken Sie daran, dass dies der Kunde ist. Es sollte auch eine serverseitige Barriere geben.
Neikos
2
@sonicboom $ locationChangeStart ist nicht sinnvoll, wenn nicht alle Routen authentifiziert werden müssen. Mit $ routeChangeStart können Sie Metadaten zu den Routenobjekten haben, z. B. ob sie authentifiziert sind oder welche Rollen für diese Route erforderlich sind. Ihr Server sollte damit umgehen, dass nicht authentifizierter Inhalt nicht angezeigt wird, und AngularJS beginnt erst mit der Verarbeitung, nachdem sich die Route geändert hat. Daher sollte nichts angezeigt werden.
Chris Nicola
93

Hier ist möglicherweise eine elegantere und flexiblere Lösung mit der Konfigurationseigenschaft "Auflösen" und "Versprechungen", die das eventuelle Laden von Daten auf das Routing und die Routingregeln in Abhängigkeit von den Daten ermöglichen.

Sie geben eine Funktion in 'Auflösen' in der Routing-Konfiguration an und führen in der Funktion Laden und Überprüfen von Daten alle Weiterleitungen durch. Wenn Sie Daten laden müssen, geben Sie ein Versprechen zurück. Wenn Sie eine Umleitung durchführen müssen, lehnen Sie das Versprechen vorher ab. Alle Details finden Sie auf den Dokumentationsseiten $ routerProvider und $ 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;
    }
};

Für russischsprachige Leute gibt es einen Beitrag auf habr " Вариант условного раутинга в AngularJS ".

Nikolay Popov
quelle
1
Warum ist die checkRouting-Funktion der Fabrik zugeordnet? Ist es wichtig, worauf es abgebildet ist?
Honkskillet
@honkskillet: Aus den eckigen $ routeProvider-Dokumenten: "factory - {string | function}: Wenn string, dann ist es ein Alias ​​für einen Dienst. Andernfalls wird if-Funktion injiziert und der Rückgabewert wird als Abhängigkeit behandelt Das Ergebnis ist ein Versprechen. Es wird aufgelöst, bevor sein Wert in den Controller eingefügt wird. Beachten Sie, dass ngRoute. $ routeParams in diesen Auflösungsfunktionen weiterhin auf die vorherige Route verweist. Verwenden Sie $ route.current.params, um auf die neuen Routenparameter zuzugreifen. stattdessen." Ebenfalls aus Dokumenten zur Lösung: "Wenn eines der Versprechen abgelehnt wird, wird das Ereignis $ routeChangeError ausgelöst."
Tim Perry
Wenn ui.routerverwendet wird, verwenden Sie $stateProvider anstelle von $routeProvider.
TRiNE
61

Ich habe versucht, das gleiche zu tun. Ich habe nach der Arbeit mit einem Kollegen eine andere einfachere Lösung gefunden. Ich habe eine Uhr aufgestellt $location.path(). Das macht den Trick. Ich fange gerade an, AngularJS zu lernen und finde, dass dies sauberer und lesbarer ist.

$scope.$watch(function() { return $location.path(); }, function(newValue, oldValue){  
    if ($scope.loggedIn == false && newValue != '/login'){  
            $location.path('/login');  
    }  
});
user1807337
quelle
Das sieht sehr interessant aus. Konnten Sie irgendwo ein Beispiel posten?
Kyleroche
3
Wo stellst du die Uhr auf?
freakTheMighty
3
@freakTheMighty Sie müssen die Uhr in Ihrer mainCtrl-Funktion einrichten, wobei ng-controller auf mainCtrl eingestellt ist. zB <body ng-controller = "mainCtrl">
user1807337
5
Ich denke, es ist nur fair, dass bei einer negativen Abstimmung ein begründeter Kommentar abgegeben werden sollte. Es wird als Lernwerkzeug helfen.
user1807337
37

Eine andere Möglichkeit, die Anmeldeumleitung zu implementieren, besteht darin, Ereignisse und Interceptors wie hier beschrieben zu verwenden . In diesem Artikel werden einige zusätzliche Vorteile beschrieben, z. B. das Erkennen, wann eine Anmeldung erforderlich ist, das Einreihen der Anforderungen in die Warteschlange und das erneute Abspielen, sobald die Anmeldung erfolgreich ist.

Sie können Demo eine Arbeits ausprobieren hier und die Demo - Quelle sehen hier .

Oran Dennison
quelle
3
Könnten Sie diese Antwort bitte aktualisieren, um die relevanten Informationen aus den Links aufzunehmen? Auf diese Weise bleibt es für Besucher auch dann nützlich, wenn die Links ausfallen.
Josliber
34

1. Legen Sie den globalen aktuellen Benutzer fest.

Legen Sie in Ihrem Authentifizierungsdienst den aktuell authentifizierten Benutzer im Stammbereich fest.

// AuthService.js

  // auth successful
  $rootScope.user = user

2. Stellen Sie die Authentifizierungsfunktion für jede geschützte Route ein.

// AdminController.js

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

3. Überprüfen Sie die Authentifizierung bei jeder Routenänderung.

// 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('/') }
    }
  })
})

Alternativ können Sie Berechtigungen für das Benutzerobjekt festlegen und jeder Route eine Berechtigung zuweisen. Überprüfen Sie dann die Berechtigung im Ereignisrückruf.

AJcodez
quelle
@malcolmhall yup, dies ist Opt-In und Sie möchten Opt-Out. if (!user && !next.$$route.public)
Fügen Sie
Könnte mir bitte jemand erklären next.$$route? Ich finde nichts in den Angular docs , dass die Argumente geben zu einem beschreiben $routeChangeStartEreignis, aber ich nehme an nextund currsind eine Art Standort Objekte? Das $$routeBit ist schwer zu googeln.
Skagedal
2
Ich sehe jetzt, dass die $$routeEigenschaft eine private Variable von Angular ist. Darauf sollten Sie sich nicht verlassen, siehe zum Beispiel: stackoverflow.com/a/19338518/1132101 - Wenn Sie dies tun, wird Ihr Code möglicherweise beschädigt , wenn sich Angular ändert.
Skagedal
2
Ich habe einen Weg gefunden, auf die Route zuzugreifen, ohne auf ein Privateigentum zuzugreifen oder eine Schleife zu durchlaufen $route.routes, um eine Liste zu erstellen (wie in der Antwort von @ thataustin): Holen Sie sich den Pfad für den Standort mit next.originalPathund verwenden Sie diesen, um zu indizieren $route.routes: var auth = $route.routes[next.originalPath].
Skagedal
Um meine Frage aus drei Kommentaren zu den Argumenten zu beantworten, die für das Ereignis vorgebracht wurden - sie scheinen tatsächlich nicht dokumentiert zu sein, lesen Sie dieses Problem, das sich auch auf diese SO-Frage bezieht: github.com/angular/angular.js/issues/ 10994
Skagedal
27

So habe ich es gemacht, falls es jemandem hilft:

In der Konfiguration habe ich ein publicAccessAttribut für die wenigen Routen festgelegt, die für die Öffentlichkeit zugänglich sein sollen (z. B. Anmelden oder Registrieren):

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

Dann setze ich in einem Ausführungsblock einen Listener für das $routeChangeStartEreignis, zu dem umgeleitet wird, es '/login'sei denn, der Benutzer hat Zugriff oder die Route ist öffentlich zugänglich:

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

Sie könnten den Zustand offensichtlich von isLoggedInetwas anderem ändern ... nur einen anderen Weg zeigen, dies zu tun.

thataustin
quelle
und was ist der Benutzer in Ihren Run-Block-Argumenten? Ein Dienst?
Mohamnag
Ja, es ist ein Dienst, der sich darum kümmert, Cookies usw. zu überprüfen, um
festzustellen,
Sie können auf die Route wie nextLoc.$$route.publicAccessübrigens zugreifen.
AJcodez
Oder verwenden Sie $route.routes[nextLoc.originalPath], die keine private Variable verwendet.
Skagedal
1
Eigentlich kann man einfach nachsehen nextLoc && nextLoc.publicAccess!
Skagedal
9

Ich mache es mit Abfangjägern. Ich habe eine Bibliotheksdatei erstellt, die der Datei index.html hinzugefügt werden kann. Auf diese Weise haben Sie eine globale Fehlerbehandlung für Ihre Rest-Service-Anrufe und müssen sich nicht um alle Fehler einzeln kümmern. Weiter unten habe ich auch meine Basic-Auth-Login-Bibliothek eingefügt. Dort können Sie sehen, dass ich auch nach dem 401-Fehler suche und an einen anderen Ort umleitung. Siehe lib / ea-basic-auth-login.js

lib / http-error-handle.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-handle.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

Fast das gleiche kann für die Anmeldung gemacht werden. Hier haben Sie die Antwort auf die Weiterleitung ($ 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
quelle
2
Sie sollten sich wirklich von Dom-Manipulationen in der JS fernhalten, es sei denn, Sie befinden sich in einer Direktive. Wenn Sie nur Ihre Logik einrichten und dann mit ng-class eine Klasse anwenden und eine CSS-Animation auslösen, werden Sie sich später bedanken.
Askdesigners
7

In Ihrer app.js-Datei:

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

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

Mit dem Angular-UI-Router ist es möglich, zu einer anderen Ansicht umzuleiten . Zu diesem Zweck haben wir die Methode $state.go("target_view"). Zum Beispiel:

 ---- 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
quelle
3

Wenn Sie keinen Angular-UI-Router verwenden möchten, aber möchten, dass Ihre Controller über RequireJS faul geladen werden, gibt es einige Probleme mit dem Ereignis $routeChangeStart bei der Verwendung Ihrer Controller als RequireJS-Module (verzögert geladen) .

Sie können nicht sicher sein, ob der Controller geladen wird, bevor er $routeChangeStartausgelöst wird - tatsächlich wird er nicht geladen. Das bedeutet, dass Sie nicht auf Eigenschaften einer nextRoute wie localsoder zugreifen können, $$routeda diese noch nicht eingerichtet sind.
Beispiel:

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

Dies bedeutet, dass Sie dort keine Zugriffsrechte überprüfen können.

Lösung:

Da das Laden des Controllers über das Auflösen erfolgt, können Sie dasselbe mit Ihrer Zugriffskontrollprüfung tun:

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

Beachten Sie hier, dass $routeChangeStartich anstelle von Ereignis verwende$routeChangeError

Ivan Hušnjak
quelle
-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
quelle
Dies ist eine grundlegende Routenkonfiguration ... Wo überprüfen wir einen Zustand, bevor wir zu den konfigurierten Routen umleiten?
TJ