-
Notifications
You must be signed in to change notification settings - Fork 3k
Description
First of all: Thank you for this great project, which gave me the power to create a perfect architecture for our huge angular app!
When upgrading ui-router to 0.2.8
, my angular 1.2.10
app only renders blank pages.
I invested several hours but wasn't able to find the cause of the problem. I hope you are able to resolve the problem. Thus, I added as much detail as possible.
Observation
My outmost ui-view
directive is set up with an ng-hide="isLoading"
and an ng-init="isLoading = true"
. The proper state controller then sets isLoading=false
as soon as it is instantiated (after all values have been resolved).
<body ng-app="app">
<ui-view ng-init="pageIsLoading = true" ng-hide="pageIsLoading"></ui-view>
</body>
angular.module('app', ['ui.router']).config(function ($stateProvider) {
$stateProvider.state('main', {
url: '/',
template: '<p>other</p>',
controller: function ($rootScope) {
$rootScope.pageIsLoading = false;
}
});
});
Here's a plunkr to reproduce the issue!
The blank page is caused by the outmost ui-view
directive in the DOM, because it has class="ng-hide"
assigned to it - so the DOM is completely compiled, but hidden.
After investigating further, I found out that the scope bound to the ui-view
references the proper scope.pageIsLoading
, which has a value of false
. Also triggering $apply()
doesn't change anything.
I'd expect the class="ng-hide"
to have been disappeared now, but this is not the case. I tripple-checked the scope values and bindings and everything seams ok, except for the class="ng-hide"
.
This problem only appears when ng-init
is used to set pageIsLoading = true
and when the ng-hide
appears directly on the ui-view
tag.
-
Using
$scope
instead of$rootScope
in the controller doesn't resolve the problem. -
Removing the
ng-init
resolves the problem, but also removes my ability to show loading spinners. -
Wrapping the
ui-view
in a div and putting theng-hide
on it also resolves the problem, but adds additional DOM elements.Example:
<body ng-app="app"> <div ng-hide="pageIsLoading"> <ui-view ng-init="pageIsLoading = true"></ui-view></div> </body>
Using git bisect
I was able to track the problem to the file src/viewDirective.js
at the specific commit a402415a2a28b360c43b9fe8f4f54c540f6c33de
by Nate Abele, which is a larger refactoring and changed a lot of things. Commits previously to this one worked fine.
I compared both versions a lot, especially by stepping through them using the Chrome debugger. Here are my ideas and what I could find out:
What might cause the problem
In src/viewDirective.js
lines 121 - 170
, function updateView()
, something interesting is happening to the vars element
and currentScope
. The function is triggered twice when loading the page once.
At the first time, the if (isDefault)
and if (!locals)
branches are executed. The second time, both are skipped and the last part of the function is executed.
When the function is invoked the second time and you stop directly at the first line, you can notice that the element
references a $jqLite
selector that contains ui-view.ng-hide
. This element is later cloned and compiled, maybe that's the reason for the ng-hide
to stick around.
With the working version, this is not the case.
What doesn't cause the problem, but looks awkward
Comparing Scope Trees
One thing I noticed is that the scope tree for nested ui-view
s looks like this in previous commits:
body 002
ui-view 002
p 003
ui-view 003
p 004
p 004
p 003
In later commits, it looks like this:
body 002
ui-view 002
p 004
ui-view 002
p 005
p 005
p 004
Although I think that it looks a little bit awkward (scope 003 is missing), ui-view always has a scope of 002 - it seams not to be related to the problem.