Skip to content

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

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
damienklinnert opened this issue Jan 28, 2014 · 6 comments
Closed

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

damienklinnert opened this issue Jan 28, 2014 · 6 comments

Comments

@damienklinnert
Copy link

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.

@nateabele
Copy link
Contributor

Awesome, thanks for the detailed write-up. I'll try to get on this later tonight.

meenie pushed a commit to meenie/ui-router that referenced this issue Feb 4, 2014
Use the linking function element instead of the template element when setting the parent.
@timkindberg
Copy link
Contributor

@meenie thanks. if you believe your comments will cause confusion for this issue please delete them.

@tautvilas
Copy link

I am having similar issue. I think this is related:

http://stackoverflow.com/questions/21308563/add-a-class-to-the-ui-view-based-on-the-current-state

It looks like that when other expressions are used in the same tag that uses ui-view directive makes these expressions interpreted with previous scope, or no scope if it is the first time.

I think this is duplicate of #866

@meenie
Copy link
Contributor

meenie commented Mar 6, 2014

@damienklinnert - This issue is fixed with #858 PR. Once more testing is done (particularly with IE), it should become 0.2.9 pretty soon.

@damienklinnert
Copy link
Author

@meenie awesome - thank you!

@meenie
Copy link
Contributor

meenie commented Mar 7, 2014

Great! Closing :).

@meenie meenie closed this as completed Mar 7, 2014
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants