[javascript] Angularjs - ng-cloak/ng-show elements blink

I have an issue in angular.js with directive/class ng-cloak or ng-show.

Chrome works fine, but Firefox is causing blink of elements with ng-cloak or ng-show. IMHO it's caused by the converting ng-cloak/ng-show to style="display: none;", probably the Firefox javascript compiler is little bit slower, so the elements appears for a while and then hide?

Example:

<ul ng-show="foo != null" ng-cloak>..</ul>

This question is related to javascript class angularjs

The answer is


Try to turn off the Firebug. I'm serious. This helps in my case.

Apply accepted answer and then make sure that Firebug in your Firefox is turned off: press F12 then turn off Firebug for this page - small button in upper right corner.



I couldn't get any of these methods to work, so I eventually did the following. For the element you want initially hidden:

<div <!--...--> style="display: none;" ng-style="style">

Then in your controller, add this at or near the top:

$scope.style = { display: 'block' };

This way, the element is initially hidden, and only shows when the controller code has actually run.

You can tune the placement to your needs, perhaps adding some logic. In my case, I switch to a login path if not currently logged in, and didn't want my interface flickering beforehand, so I set $scope.style after the logged-in check.


I had a problem where a <div ng-show="expression"> would be initially visible for a fraction of a second, even though "expression" was initially false, before the ng-show directive got a chance to run.

The solution I used was to manually add the "ng-hide" class, as in <div ng-show="expression" ng-hide>, to make sure it started initially hidden. The ng-show directive will add/remove the ng-hide class as necessary after that.


you'd better reference angular document, becuase the version[1.4.9] has update to below that make it could support data-ng-cloak directive.

[ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak {
  display: none !important;
}

I'm using ng-show in a directive to show and hide popups.

<div class="..." ng-show="showPopup">

None of the above worked for me, and using ng-if instead of ng-show would be an overkill. That would imply removing and adding the whole popup content into the DOM at every single click. Instead I added an ng-if into the same element to make sure it doesn't show at the document load:

<div class="..." ng-show="showPopup" ng-if="popupReady">

Afterwards I added the initialization into the controller responsible of this directive with a timeout:

$timeout(function () {
    $scope.popupReady = true;
});

This way I eliminated the flickering issue and avoided the costly operation of DOM insertion at every single click. This came at an expense of using two scope variables for the same purpose instead of one, but so far this is definitely the best option.


We ran into this problem at our company and solved it by adding "display: none" to the CSS styling for those flickering ng-show elements. We didn't have to use ng-cloak at all. Unlike others in this thread, we experienced this issue in Safari but not Firefox or Chrome -- possibly due to Safari's lazy repaint bug in iOS7.


Avoid line break

<meta http-equiv="Content-Security-Policy"              content="
default-src 'FOO';   
script-src 'FOO';    
style-src  'FOO'; 
font-src 'FOO';">

Works with Firefox 45.0.1

<meta http-equiv="Content-Security-Policy"              content="    default-src 'FOO';    script-src 'FOO';     style-src  'FOO';    font-src 'FOO';">

I personally decided to use the ng-class attribute rather than the ng-show. I've had a lot more success going this route especially for pop-up windows that are always not shown by default.

What used to be <div class="options-modal" ng-show="showOptions"></div>

is now: <div class="options-modal" ng-class="{'show': isPrintModalShown}">

with the CSS for the options-modal class being display: none by default. The show class contains the display:block CSS.


Make sure AngularJS is included in the head of the HTML. See ngCloak doc:

For the best result, angular.js script must be loaded in the head section of the html file; alternatively, the css rule (above) must be included in the external stylesheet of the application.


I tried the ng-cloak solution above but it still has intermittent issues with Firefox. The only workaround that worked for me is to delay the loading of the form until Angular is fully loaded.

I simply added ng-init in the app and use ng-if at the form side to check if the variable I set is already loaded.

<div ng-app="myApp" ng-init="loaded='yes'"> 
   <form ng-if="loaded.length > 0">
      <!--all my elements here-->
   </form>
</div>

It's better to use ng-if instead of ng-show. ng-if completely removes and recreates the element in the DOM and helps to avoid ng-shows blinking.


Tried ng-cloak but still brief blinks. Below code rid them completely.

<body style="display:none;" ng-style="{'display':'block'}">

As mentioned in the documentation, you should add a rule to your CSS to hide it based on the ng-cloak attribute:

[ng\:cloak], [ng-cloak], .ng-cloak {
    display: none;
}

We use similar tricks on the "Built with Angular" site, which you can view the source of on Github: https://github.com/angular/builtwith.angularjs.org

Hope that helps!


ngBind and ngBindTemplate are alternatives that do not require CSS:

<div ng-show="foo != null" ng-cloak>{{name}}</div>  <!-- requires CSS -->
<div ng-show="foo != null" ng-bind="name"></div>
<div ng-show="foo != null" ng-bind-template="name = {{name}}"></div>

In addition to other answers, if you find the flash of template code to still be occuring it is likely you have your scripts at the bottom of the page and that means that the ng-cloak directive straight up will not work. You can either move your scripts to the head or create a CSS rule.

The docs say "For the best result, the angular.js script must be loaded in the head section of the html document; alternatively, the css rule above must be included in the external stylesheet of the application."

Now, it doesn't have to be an external stylesheet but just in a element in the head.

<style type="text/css">
  .ng-cloak {
    display: none !important;
  }
</style>

source: https://docs.angularjs.org/api/ng/directive/ngCloak


For what it's worth, I had a similar issue ng-cloak not working. It may be worth checking your app/site with cache enabled to reuse source files to see if that helps.

With my run-in with flickering, I was testing with DevTools open and cache disabled. Leaving the panel closed with caching enabled fixed my issue.


In addition to the accepted answer if you're using an alternative method of triggering ng-cloak...

You may also wish to add some additional specificities to your CSS/LESS:

[ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak],
.ng-cloak, .x-ng-cloak,
.ng-hide {
    display: none !important;
}

There's actually two separate problems that can cause the flicker issue and you could be facing either one or both of these.

Problem 1: ng-cloak is applied too late

This issue is solved as descibed in many of the answers on this page is to make sure AngularJS is loaded in the head. See ngCloak doc:

For the best result, angular.js script must be loaded in the head section of the html file; alternatively, the css rule (above) must be included in the external stylesheet of the application.

Problem 2: ng-cloak is removed too soon

This issue is most likely to occur when you have a lot of CSS on your page with rules cascading over one another and the deeper layers of CSS flash up before the top layer is applied.

The jQuery solutions in answers involving adding style="display:none" to your element do solve this issue so long as the style is removed late enough (in fact these solutions solve both problems). However, if you prefer not to add styles directly to your HTML you can achieve the same results using ng-show.

Starting with the example from the question:

<ul ng-show="foo != null" ng-cloak>..</ul>

Add an additional ng-show rule to your element:

<ul ng-show="isPageFullyLoaded && (foo != null)" ng-cloak>..</ul>

(You need to keep ng-cloak to avoid problem 1).

Then in your app.run set isPageFullyLoaded:

app.run(['$rootScope', function ($rootScope) {
    $rootScope.$safeApply = function (fn) {
        $rootScope.isPageFullyLoaded = true;
    }
}]);

Be aware that depending on exactly what you're doing, app.run may or may not be the best place to set isPageFullyLoaded. The important thing is to make sure that isPageFullyLoaded gets set to true after whatever it is you don't want to flicker is ready to be revealed to the user.

It sounds like Problem 1 is the problem the OP is hitting, but others are finding that solution does not work or only partially works because they are hitting Problem 2 instead or as well.

Important Note: Be sure to apply solutions to both ng-cloak being applied too late AND removed to soon. Solving only one of these problems may not relieve the symptoms.


I would would wrap the <ul> with a <div ng-cloak>


Keeping the below statements in head tag fixed this issue

<style type="text/css">
    [ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak {
    display: none !important;
}
</style>

official documentation


AS from the above discussion

[ng-cloak] {
                display: none;
            }

is the perfect way to solve the Problem.


I had a similar issue and found out that if you have a class that contains transitions, the element will blink. I tried to add ng-cloak without success, but by removing the transition the button stopped blinking.

I'm using ionic framework and the button-outline has this transition

.button-outline {
  -webkit-transition: opacity .1s;
  transition: opacity .1s;
}

Simply overwrite the class to remove the transition and the button will stop blinking.

Update

Again on ionic there is a flicker when using ng-show/ng-hide. Adding the following CSS resolves it:

.ng-hide-add,
.ng-hide-remove {
  display: none !important;
}

Source: http://forum.ionicframework.com/t/beta-14-ng-hide-show/14270/9


I've never had much luck using ngCloak. I still get flickering despite everything mentioned above. The only surefire way to avoid flicking is to put your content in a template and include the template. In a SPA, the only HTML that will get evaluated before being compiled by Angular is your main index.html page.

Just take everything inside the body and stick it in a separate file and then:

<ng-include src="'views/indexMain.html'"></ng-include>

You should never get any flickering that way as Angular will compile the template before adding it to the DOM.


I actually found the suggestion from Rick Strahl's Web Log fixed my issue perfectly (as I still had the odd issue with ng-cloak blinking raw {{code}} at times, especially while running Firebug):

The nuclear option: Hiding the Content manually

Using the explicit CSS is the best choice, so the following shouldn’t ever be necessary. But I’ll mention it here as it gives some insight how you can hide/show content manually on load for other frameworks or in your own markup based templates.

Before I figured out that I could explicitly embed the CSS style into the page, I had tried to figure out why ng-cloak wasn’t doing its job. After wasting an hour getting nowhere I finally decided to just manually hide and show the container. The idea is simple – initially hide the container, then show it once Angular has done its initial processing and removal of the template markup from the page.

You can manually hide the content and make it visible after Angular has gotten control. To do this I used:

<div id="mainContainer" class="mainContainer boxshadow"
    ng-app="app" style="display:none">

Notice the display: none style that explicitly hides the element initially on the page.

Then once Angular has run its initialization and effectively processed the template markup on the page you can show the content. For Angular this ‘ready’ event is the app.run() function:

app.run( function ($rootScope, $location, cellService) {        
    $("#mainContainer").show();
    …
});

This effectively removes the display:none style and the content displays. By the time app.run() fires the DOM is ready to displayed with filled data or at least empty data – Angular has gotten control.


None of the solutions listed above worked for me. I then decided to look at the actual function and realised that when “$scope.watch ” was fired, it was putting a value in the name field which was not meant to be the case. So in the code I set and oldValue and newValue then

$scope.$watch('model.value', function(newValue, oldValue) {
if (newValue !== oldValue) {
validateValue(newValue);
}
});

Essentially when scope.watch is fired in this case, AngularJS monitors the changes to the name variable (model.value)


I tried every solution posted here and still got flickering in Firefox.

If it helps anyone, I solved it by adding style="display: none;" to the main content div, then using jQuery (I was already using it on the page) $('#main-div-id').show(); once everything was loaded after getting data from the server;


I tried all of the answers above and nothing worked. Using ionic to develop a hybrid app and was trying to make an error message not flicker. I ended up solving my issue by adding an ng-hide class to my element. My div already has ng-show to show the element when there is an error. Adding ng-hide set the div to not display before angular is loaded. No ng-cloak or adding angular to the head necessary.


Examples related to javascript

need to add a class to an element How to make a variable accessible outside a function? Hide Signs that Meteor.js was Used How to create a showdown.js markdown extension Please help me convert this script to a simple image slider Highlight Anchor Links when user manually scrolls? Summing radio input values How to execute an action before close metro app WinJS javascript, for loop defines a dynamic variable name Getting all files in directory with ajax

Examples related to class

String method cannot be found in a main class method Class constructor type in typescript? ReactJS - Call One Component Method From Another Component How do I declare a model class in my Angular 2 component using TypeScript? When to use Interface and Model in TypeScript / Angular Swift Error: Editor placeholder in source file Declaring static constants in ES6 classes? Creating a static class with no instances In R, dealing with Error: ggplot2 doesn't know how to deal with data of class numeric Static vs class functions/variables in Swift classes?

Examples related to angularjs

AngularJs directive not updating another directive's scope ERROR in Cannot find module 'node-sass' CORS: credentials mode is 'include' CORS error :Request header field Authorization is not allowed by Access-Control-Allow-Headers in preflight response WebSocket connection failed: Error during WebSocket handshake: Unexpected response code: 400 Print Html template in Angular 2 (ng-print in Angular 2) $http.get(...).success is not a function Angular 1.6.0: "Possibly unhandled rejection" error Find object by its property in array of objects with AngularJS way Error: Cannot invoke an expression whose type lacks a call signature