问题
So It took me a very long time to understand this issue and get to a mcve. Here is the case : I'm trying to redirect a user to a login page when he's not authenticated (this is very basic). Here is the code :
HTML :
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.6/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.13/angular-ui-router.min.js"></script>
<script src="js/app.js"></script>
</head>
<body ng-app="starter">
<div ui-view></div>
<script id="login.html" type="text/ng-template">
l
</script>
<script id="welcome.html" type="text/ng-template">
w
</script>
</body>
</html>
JS :
angular.module('starter', ['ui.router'])
.run(["$rootScope", "$state", function($rootScope, $state) {
$rootScope.$on("$stateChangeError", function(event, toState, toParams, fromState, fromParams, error) {
if (error === "nope") {
$state.go("login");
}
});
}])
.config(function($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('/welcome');
$stateProvider
.state('welcome', {
url: '/welcome',
templateUrl: 'welcome.html',
resolve: {
"auth": ["$q", function($q) {
return $q.reject("nope");
}]
}
})
.state('login', {
url: '/login',
templateUrl: 'views/login.html'
})
});
The "views/login.html" contains just "vl" to see it showing on the screen. So, when the above code is ran, the output is good, but look at the Chrome console :
Now, the crazy part of it, is if you modify the JS and replace
templateUrl: 'views/login.html'
in the login state by simply
templateUrl: 'login.html'
using the ng-template defined in the html, ALL IS GOOD ! So well, I guess using a file as template must trigger some watcher or whatever... Well no, I'm just out of ideas.
Thanks ahead for your help !
[EDIT]
here are two things that could help :
- There is no error when using ngRoute in place of UI Router
- There is no error if replacing Angular version with the 1.2.25
So I think it's a bug with UI Router and Angular 1.3. But don't know at all what to do to solve it.
回答1:
You need to call event.preventDefault()
before you call $state.go()
.
See here: http://plnkr.co/edit/eUosIpdN7adJFxfDo3kV?p=preview
The main reason this error is occuring, as you have already identified, is that the template url 'views/login.html'
doesn't exsit. You said that when you changed the template url from 'views/login.html'
to 'login.html'
everything worked, and this makes sense because that template does exist.
The reason you are seeing the infinite digest error is that each time you try to access the welcome
state the auth
resolver is throwing an error which triggers the $stateChangeError
event like you would expect it too. Everything is fine up until the point when it tries to go to the login
state. Attempting to transition to the login
state fails because the template url 'views/login.html'
doesn't exist, and this failure is causing your otherwise
redirect to bring you back to the welcome
state. You can see at this point that arriving back at the welcome
state will restart the whole cycle and cause the infinite digest loop.
Simply ensuring that your template urls are correct should prevent this from happening, as you have already discovered.
回答2:
I have had the same problem and this is how I solved it
.run(function($rootScope, $state) {
$rootScope.$on('$stateChangeError', function() {
// Redirect user to our login page
$state.go('auth.login');
});
});
Below I pasted my entire page so you can see how it all works together 'use strict';
angular.module('mean.pdash').config(['$stateProvider',
function($stateProvider) {
// Check if the user is connected
var checkLoggedin = function($q, $timeout, $http, $location) {
// Initialize a new promise
var deferred = $q.defer();
$http.get('/loggedin').success(function(user) {
// Authenticated
console.log(user);
if (user !== '0') {
$timeout(deferred.resolve);
} else {
$timeout(deferred.reject);
}
});
return deferred.promise;
};
$stateProvider.state('pdash', {
url: '/',
templateUrl: 'pdash/views/index.html',
controller: 'PdashController',
resolve: {
checkLoggedin: checkLoggedin
}
});
}
])
.run(function($rootScope, $state) {
$rootScope.$on('$stateChangeError', function() {
// Redirect user to our login page
$state.go('auth.login');
});
});
来源:https://stackoverflow.com/questions/27710247/angular-ui-router-issue-when-redirecting-to-a-template-after-resolve-throws-er