I've boiled the code down as much as I can. Something about nested states and the event handling/broadcasting is causing an infinite loop. In Chrome I can pause it and see that it is looping forever in Angular's $digest
function. Any idea why? Is it a bug in my example code, or a bug in Angular, or the UI Router?
<!doctype html>
<html ng-app='bugapp' ng-controller='BugAppCtrl'>
<head>
<script src='//code.jquery.com/jquery-1.10.1.min.js'></script>
<!-- Angular 1.2.11 -->
<script src='//ajax.googleapis.com/ajax/libs/angularjs/1.2.11/angular.js'></script>
<!-- UI router 0.2.8 -->
<script src='//cdn.jsdelivr.net/angular.ui-router/0.2.8/angular-ui-router.js'></script>
<script>
angular.module('bugapp', ['ui.router'])
.run(function ($rootScope, $state, $stateParams) {
$rootScope.$state = $state;
$rootScope.$stateParams = $stateParams;
})
.config(function ($locationProvider, $stateProvider, $urlRouterProvider) {
$locationProvider.html5Mode(false);
$stateProvider
.state("root", {
abstract: true,
url: "/servletContext?asUser",
template: '<div ui-view></div>' // ???
})
.state("root.home", {
abstract: true,
url: "/home",
template: "<div ng-if='hasData()' ui-view ></div>"
})
.state("root.home.profile", {
url: "/profile",
template: '<div>whatever</div>'
})
})
.controller('BugAppCtrl', function ($scope, $state, $stateParams, $log, $location) {
$log.log('BugAppCtrl: constructor');
$scope.hasData = function() {
var res = !!$scope.foo;
// $log.log("hasData called, returing " + res + " foo is " + $scope.foo);
return res;
};
$scope.$on('$stateChangeSuccess', function () {
$log.log("State changed! (to " + $state.current.name + ")");
$scope.foo = 'junk';
$scope.$broadcast("resetfoo");
});
$state.go('root.home.profile');
});
</script>
</head>
<body>
<div ui-view></div>
</body>
</html>
I suspect this is a bug in the UI Router, for two reasons:
Even if you keep using version 0.2.8 of UI Router, if you perform the state change through $location instead of $state, it works. Here's an example of using $location instead of the $state.go call:
$location.path('/servletContext/home/profile');
Although I use and recommend UI Router (can't do without nested views), if you find in the future that you want to do any sort of intercepting or redirecting when the user tries to go to certain pages, I recommend using $location.path instead of $state, for reasons I described in a blog post
Edit: I haven't tried with parameters before but just tried with the code you posted (I created a 2nd controller and assigned it to your 'root.home.profile' state), and it works. Instructions from UI Router are here. But basically if you set your URL in your state definition the same way you would with UI Router:
url: "/profile/:foo",
then in your $location.path call add the parameter in the path:
$location.path('/servletContext/home/profile/12');
and you can access the 12 in the controller from
$stateParams.foo
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With