Salami
Salami

Reputation: 3117

ng-cloak directive gets removed too early

I have an angular-js app with some controllers that shouldn't be shown initially. They flash on the screen despite my use of ng-cloak. The problem seems to be that compile gets called and removes the ng-cloak directives and class, this makes the controllers contents visible even though it shouldn't be because ng-show is false.

If I pause js execution in ng-cloak's compile method I can see the elements appear as the ng-cloak directive is removed. If I pause js execution in the controller (for example on "$scope.visible = false;") I can see the controller stays visible on the page. The controller is then invisible again as it should be sometime later in loading.

How can I prevent this flashing? Why doesn't ng-cloak pay respect to ng-show?

index.html:

<div ng-cloak class="ng-cloak" ng-controller="RoomsController" ng-show="visible">
    <h1>This flashes, it can be seen if we set a breakpoint in the controller js, or after the ng-cloak directive's compile method in angular.js</h1>
</div>

app.js:

app.controller('RoomsController', ['$scope',
    function ($scope) {
        $scope.visible = false;
    }
]);

Upvotes: 9

Views: 6254

Answers (5)

vit
vit

Reputation: 2685

After a lot messing around I managed to "fix" this by adding ng-hide class to the element, while removing ng-cloak completely:

<div class="ng-hide" ng-controller="RoomsController" ng-show="visible">
    <h1>This flashes, it can be seen if we set a breakpoint in the controller js, or after the ng-cloak directive's compile method in angular.js</h1>
</div>

This hides the element initially. Angular then removes the ng-hide class when processing the ng-show directive.

Upvotes: 2

Gil Birman
Gil Birman

Reputation: 35900

I had a similar problem with ngCloak in IE mobile. The simplest solution I came up with is similar to some of the other answers, but I use ng-show instead, and without any extra $scope variables:

<div class="ng-hide" ng-show="true">
  {{mydata}}
</div>

The solution requires that you add the ng-hide class and ng-show="true". This ensures that the element will only be visible after the ng-show directive is linked.

Upvotes: 14

Theluckin
Theluckin

Reputation: 359

use a ng-hide in the class, JS will take it off or set it again even if its there but till JS kicks in it can sit there and use CSS to hide your div

<div data-ng-controller="RoomsController">
    <div ng-cloak class="ng-cloak ng-hide" data-ng-if="visible" >
        Some text
    </div>        
</div>

Upvotes: 0

Łukasz Wiatrak
Łukasz Wiatrak

Reputation: 2767

I've reproduced your issue and the thing that worked for me was to create inner div and use ng-if directive instead of ng-show. I hope it helps.

<div data-ng-controller="RoomsController">
    <div ng-cloak class="ng-cloak" data-ng-if="visible" >
        Some text
    </div>        
</div>

Upvotes: 2

Umur Kontacı
Umur Kontacı

Reputation: 35478

ngCloak directive hides the related elements until the end compile process. This is useful for hiding {{ someBinding }} stuff, and probably nothing else. The actual linking and binding in the linking process.

To prevent flashing of an element, it shouldn't be there until the application bootstraps itself. You can take a look at ngInclude for simple widgets, and ngView for bigger, complex things.

Upvotes: 1

Related Questions