Skip to content

0.2.8 breaks ng-init in combination with ng-hide and ui-view #834

@damienklinnert

Description

@damienklinnert

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 the ng-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-views 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions