Mengarahkan kembali ke rute tertentu berdasarkan kondisi

493

Saya sedang menulis aplikasi AngularJS kecil yang memiliki tampilan masuk dan tampilan utama, dikonfigurasi seperti:

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

LoginController saya memeriksa kombinasi pengguna / pass dan menetapkan properti pada $ rootScope yang mencerminkan ini:

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

Semuanya berfungsi, tetapi jika saya mengakses http://localhost/#/mainsaya akhirnya melewati layar login. Saya ingin menulis sesuatu seperti "setiap kali rute berubah, jika $ rootScope.loggedUser adalah null maka redirect ke / login"

...

... tunggu. Bisakah saya mendengarkan perubahan rute entah bagaimana? Saya akan tetap mengirimkan pertanyaan ini dan terus mencari.

tidak pernah
sumber
3
Hanya untuk memperjelas: sementara banyak solusi di bawah ini berfungsi dengan baik, saya baru-baru ini lebih cenderung untuk menerima jawaban @ Oran di bawah ini - yaitu, minta server merespons dengan kode 401 ketika diminta untuk URL sensitif, dan gunakan informasi itu untuk mengontrol "kotak masuk" pada klien. (Namun juri masih keluar pada "antrian permintaan ditolak dan menerbitkan kembali nanti" sedikit, setidaknya untuk saya :))
st.never

Jawaban:

510

Setelah beberapa menyelam melalui beberapa dokumentasi dan kode sumber, saya pikir saya berhasil. Mungkin ini akan bermanfaat bagi orang lain?

Saya menambahkan yang berikut ini ke konfigurasi modul saya:

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

Satu hal yang tampaknya aneh adalah bahwa saya harus menguji nama parsial ( login.html) karena objek Route "berikutnya" tidak memiliki url atau sesuatu yang lain. Mungkin ada cara yang lebih baik?

tidak pernah
sumber
13
Pria keren, terima kasih telah berbagi solusi Anda. Satu hal yang perlu diperhatikan: dalam versi saat ini, "berikutnya. $ Route.templateUrl"
doubledriscoll
5
Jika Anda melihat permintaan jaringan di chrome inspector, rute yang sedang dialihkan (karena pengguna tidak masuk) masih dipanggil dan respons dikirimkan ke browser, dan kemudian jalur yang dialihkan '/ login' dipanggil. Jadi metode ini tidak bagus karena pengguna yang tidak masuk log dapat melihat respons untuk rute yang seharusnya tidak mereka akses.
sonicboom
34
Gunakan $ locationChangeStart alih-alih $ routeChangeStart untuk mencegah rute dipanggil dan membiarkan pengguna yang tidak diautentikasi melihat konten yang seharusnya tidak mereka akses.
sonicboom
17
Ingatlah bahwa ini adalah klien. Seharusnya juga ada penghalang sisi server.
Neikos
2
@sonicboom $ locationChangeStart tidak masuk akal jika tidak semua rute memerlukan otentikasi, dengan $ routeChangeStart Anda dapat memiliki metadata pada objek rute, seperti apakah itu diautentikasi atau tidak, peran apa yang diperlukan untuk rute itu. Server Anda seharusnya menangani tidak menampilkan konten yang tidak diautentikasi dan AngularJS tidak akan mulai memproses sampai setelah rute berubah, jadi tidak ada yang ditampilkan.
Chris Nicola
93

Berikut ini mungkin solusi yang lebih elegan dan fleksibel dengan properti konfigurasi 'tekad' dan 'janji' yang memungkinkan pemuatan data akhir pada aturan routing dan routing tergantung pada data.

Anda menentukan fungsi dalam 'menyelesaikan' dalam konfigurasi rute dan pada fungsi memuat dan memeriksa data, lakukan semua pengalihan. Jika Anda perlu memuat data, Anda mengembalikan janji, jika Anda perlu melakukan redirect - tolak janji sebelumnya. Semua detail dapat ditemukan di $ routerProvider dan halaman dokumentasi $ 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;
    }
};

Untuk orang-orang berbahasa Rusia ada posting di habr " Вариант условного раутинга в AngularJS ."

Nikolay Popov
sumber
1
mengapa fungsi checkRouting dipetakan ke pabrik? Apakah penting apa yang dipetakan?
honkskillet
@honkskillet: Dari $ docProvider sudut dokumen: "factory - {string | function}: Jika string maka itu adalah alias untuk layanan. Jika tidak berfungsi, maka itu disuntikkan dan nilai kembali diperlakukan sebagai ketergantungan. Jika hasilnya adalah janji, itu diselesaikan sebelum nilainya disuntikkan ke controller. Sadarilah bahwa ngRoute. $ routeParams masih akan merujuk ke rute sebelumnya dalam fungsi tekad ini. Gunakan $ route.current.params untuk mengakses parameter rute baru, sebagai gantinya." Juga dari dokumen pada resolusi: "Jika salah satu janji ditolak, acara $ routeChangeError dipecat."
Tim Perry
Jika ui.routerdigunakan, gunakan $stateProvider sebagai ganti $routeProvider.
TRiNE
61

Saya telah mencoba melakukan hal yang sama. Datang dengan solusi sederhana lain setelah bekerja dengan seorang rekan. Saya memiliki jam tangan yang sudah diatur $location.path(). Itu yang berhasil. Saya baru mulai belajar AngularJS dan menemukan ini menjadi lebih bersih dan mudah dibaca.

$scope.$watch(function() { return $location.path(); }, function(newValue, oldValue){  
    if ($scope.loggedIn == false && newValue != '/login'){  
            $location.path('/login');  
    }  
});
pengguna1807337
sumber
Ini terlihat sangat menarik. Apakah Anda dapat memposting contoh di suatu tempat?
kyleroche
3
Di mana Anda mengatur arloji?
freakTheMighty
3
@freakTheMighty Anda harus mengatur arloji di fungsi mainCtrl Anda, di mana ng-controller diatur ke mainCtrl. mis. <body ng-controller = "mainCtrl">
user1807337
5
Saya pikir itu adil bahwa jika ada suara negatif yang diberikan, itu harus memiliki komentar dengan alasan. Ini akan membantu sebagai alat pembelajaran.
user1807337
37

Cara berbeda untuk menerapkan pengalihan login adalah dengan menggunakan acara dan pencegat seperti yang dijelaskan di sini . Artikel ini menjelaskan beberapa keuntungan tambahan seperti mendeteksi kapan login diperlukan, mengantri permintaan, dan memutarnya kembali setelah login berhasil.

Anda dapat mencoba demo yang berfungsi di sini dan melihat sumber demo di sini .

Oran Dennison
sumber
3
Bisakah Anda memperbarui jawaban ini untuk memasukkan informasi yang relevan dari tautan? Dengan begitu hal itu akan terus bermanfaat bagi pengunjung bahkan jika tautannya turun.
josliber
34

1. Tetapkan pengguna global saat ini.

Di layanan otentikasi Anda, setel pengguna yang saat ini diautentikasi pada cakupan root.

// AuthService.js

  // auth successful
  $rootScope.user = user

2. Atur fungsi auth pada setiap rute yang dilindungi.

// AdminController.js

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

3. Periksa auth pada setiap perubahan rute.

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

Sebagai alternatif, Anda dapat mengatur izin pada objek pengguna dan memberikan izin pada setiap rute, lalu memeriksa izin dalam panggilan balik acara.

AJcodez
sumber
@malcolmhall ya, ini opt-in dan Anda ingin opt-out. Alih-alih menambahkan boolean "publik" ke rute publik seperti halaman login, dan redirectif (!user && !next.$$route.public)
AJcodez
Bisakah seseorang tolong jelaskan next.$$routekepada saya? Saya tidak menemukan apa pun dalam dokumen Sudut yang menjelaskan argumen yang diberikan pada suatu $routeChangeStartperistiwa, tetapi saya berasumsi nextdan currapakah ada semacam objek lokasi? The $$routebit sulit untuk google.
skagedal
2
Saya melihat sekarang bahwa $$routeproperti adalah variabel pribadi Angular. Anda seharusnya tidak mengandalkan itu, lihat misalnya: stackoverflow.com/a/19338518/1132101 - jika Anda melakukannya, kode Anda mungkin rusak ketika perubahan Angular.
skagedal
2
Saya telah menemukan cara untuk mengakses rute tanpa mengakses properti pribadi atau harus loop melalui $route.routesuntuk membangun daftar (seperti dalam jawaban @ thataustin ini): mendapatkan jalan untuk lokasi dengan next.originalPathdan menggunakan itu untuk indeks $route.routes: var auth = $route.routes[next.originalPath].
skagedal
Untuk menjawab pertanyaan saya dari tiga komentar yang lalu tentang argumen yang diberikan pada acara tersebut - mereka sepertinya memang tidak berdokumen, lihat masalah ini yang juga merujuk pada pertanyaan SO ini: github.com/angular/angular.js/issues/ 10.994
skagedal
27

Begini cara saya melakukannya, kalau-kalau itu membantu siapa pun:

Di konfigurasi, saya menetapkan publicAccessatribut pada beberapa rute yang ingin saya buka untuk umum (seperti login atau daftar):

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

kemudian dalam menjalankan blok, saya menetapkan pendengar pada $routeChangeStartacara yang dialihkan ke '/login'kecuali pengguna memiliki akses atau rute dapat diakses secara publik:

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

Anda jelas dapat mengubah kondisi dari yang isLoggedInlain ... hanya menunjukkan cara lain untuk melakukannya.

thataustin
sumber
dan apa pengguna dalam argumen run block Anda? sebuah layanan?
mohamnag
ya, ini adalah layanan yang menangani pengecekan cookie, dll. untuk melihat apakah pengguna masuk.
thataustin
Anda dapat mengakses rute seperti nextLoc.$$route.publicAccessbtw.
AJcodez
Atau gunakan $route.routes[nextLoc.originalPath], yang tidak menggunakan variabel pribadi.
skagedal
1
Sebenarnya, Anda bisa mengeceknya nextLoc && nextLoc.publicAccess!
skagedal
9

Saya melakukannya menggunakan pencegat. Saya telah membuat file perpustakaan yang dapat ditambahkan ke file index.html. Dengan cara ini Anda akan memiliki penanganan kesalahan global untuk panggilan layanan lainnya dan tidak perlu peduli tentang semua kesalahan secara individual. Lebih jauh ke bawah saya juga menempelkan perpustakaan login autentik dasar saya. Di sana Anda dapat melihat bahwa saya juga memeriksa kesalahan 401 dan mengalihkan ke lokasi yang berbeda. Lihat lib / ea-basic-auth-login.js

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

Hampir sama bisa dilakukan untuk login. Di sini Anda memiliki jawaban untuk pengalihan ($ 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
sumber
2
Anda benar-benar harus tinggal jauh dari melakukan manipulasi dom di JS kecuali Anda dalam arahan. Jika Anda hanya mengatur logika Anda dan kemudian menggunakan ng-class untuk menerapkan kelas dan memicu animasi CSS Anda akan berterima kasih kepada diri sendiri nanti.
Askdesigners
7

Dalam file app.js Anda:

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

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

Dimungkinkan untuk mengalihkan ke tampilan lain dengan angular-ui-router . Untuk tujuan ini, kami memiliki metode $state.go("target_view"). Sebagai contoh:

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

Jika Anda tidak ingin menggunakan angular-ui-router, tetapi ingin agar controller Anda dimuat melalui RequireJS, ada beberapa masalah dengan kejadian $routeChangeStartketika menggunakan controller Anda sebagai modul RequireJS (lazy loaded).

Anda tidak dapat memastikan pengontrol akan dimuat sebelum $routeChangeStartdipicu - sebenarnya itu tidak akan dimuat. Itu berarti Anda tidak dapat mengakses properti nextseperti rute localsatau $$routekarena mereka belum diatur.
Contoh:

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

Ini berarti Anda tidak dapat memeriksa hak akses di sana.

Larutan:

Karena memuat pengontrol dilakukan melalui tekad, Anda dapat melakukan hal yang sama dengan pemeriksaan kontrol akses Anda:

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

Perhatikan di sini bahwa alih-alih menggunakan acara yang $routeChangeStartsaya gunakan$routeChangeError

Ivan Hušnjak
sumber
-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
sumber
Ini adalah konfigurasi rute dasar ... Di mana kita memeriksa kondisi apa pun sebelum mengarahkan kembali ke rute yang dikonfigurasi ..?
TJ