Home » Angularjs » How to correctly use ng-cloak directive?

How to correctly use ng-cloak directive?

Posted by: admin November 7, 2017 Leave a comment

Questions:

Somehow, ng-cloak in AngularJS doesn’t work.
I want to hide {{ }} while loading the page. Because it looks awful.

<!DOCTYPE html>
<html lang="en" ng-app>
    <head>
        <meta charset="UTF-8">
        <title>Angular Sample</title>
    </head>
    <body ng-model="isShow" ng-init="isShow=true">

        <p ng-show="isShow"><span ng-cloak>{{ isShow }}</span></p>
        <p ng-show="!isShow"><span ng-cloak>{{ isShow }}</span></p>

        <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script>
    </body>
</html>
Answers:

Add this css from here

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

and use either the class name or attribute on your parent div or anywhere you have defined your app.

eg:

<div ng-app="Random" class="ng-cloak">
</div>

Questions:
Answers:

From the Angular docs:

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.

Questions:
Answers:

You have to specify these rules in your CSS:

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

Questions:
Answers:

Add below in your css file:-

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

Questions:
Answers:

Using ngBind should eliminate that as well (I develop in SharePoint sometimes and ngCloak won’t work).

AngularJS Docs:

It is preferable to use ngBind instead of {{ expression }} if a
template is momentarily displayed by the browser in its raw state
before Angular compiles it. Since ngBind is an element attribute, it
makes the bindings invisible to the user while the page is loading.

An alternative solution to this problem would be using the ngCloak
directive.

JS:

var app = angular.module('test', []);

app.controller('testCtrl', ['$scope', function($scope) {
  $scope.test = "Hello World";
}]);

HTML:

<html ng-app="test">

<head>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
  <script src="script.js"></script>
</head>

<body ng-controller="testCtrl">
  <h1 ng-bind="test"></h1>
</body>

</html>

Questions:
Answers:

My solution
I think i tried all of above suggestions but nothing worked. Some uses ng-include but it seems a little bit to much, further it could be scary with the inner scope that gets created. So it tried it by using style and ng-style.
In my affected main div.

<div class="container" style="display:hidden;" ng-style="loaded">

Then I set the scope variable loaded in my base controller.

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

Still got all those {{ }}. Weird when display sets to block only when angularjs has loaded. Then I noticed that I had the firefox f12 developer console running. Its doing stuff. Stupid me

Questions:
Answers:

From angular 1.3 onwards, you must specify a name for ng-app attribute for it to work.

<html lang="en" ng-app="myApp">

IN your JS:

angular.module("myApp",[])

This will make the angular to bootstrap.

But for the current situation, as you are loading angular at the bottom of the page, it’s taking time to load. So the css required for the ng-cloak is not available yet.

Either move the js to the tag or load the specific CSS code to your CSS to make it work.

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

Questions:
Answers:

In my case, I figured that my troubles was dues to pending ajax requests. Ng-cloak probably works for static content, but if a template depends an ajax data then this is thus rendered before receiving the ajax response.

To avoid it I define a directive :

angu

mymodule
        .directive("ajaxCloak", ['$interval', '$http', function ($interval, $http) {
            return {
                restrict: 'A',
                link: function (scope, element, attrs) {
                    let stop = $interval(() => {
                        if ($http.pendingRequests.length === 0) {
                            $interval.cancel(stop);
                            attrs.$set("ajaxCloak", undefined);
                            element.removeClass("ajax-cloak");
                        }
                    }, 100);

                }
            };
        }]);

With a bit of CSS :

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

Then in your main HTML file:

<div ui-view data-ajax-cloak></div>

Note: this isn’t as sophisticated as ng-cloak as this is a global cloack, it hides everything until all requests are finished.

Questions:
Answers:

I have tried all of the answers above and a lot beyond, with no help. My (large) page would flicker on each load.
My solution was to add this just after body tag:

<div style="display:flex" opacity=0>
  <status-progress></status-progress>
  <h3>Loading... </h3>
</div>

and to wrap everything in the page:

<div class="loaded" style="opacity: 0" opacity=1> ... </div>

directive:

app.directive('opacity', opacity);
    function opacity($timeout) {
        return {
            link: function (scope, element, attrs) {
                var value = attrs.opacity;
                $timeout(function () {
                    element[0].style.opacity = value;
                },500);
            }
        }
    }

To make the page appear “smoother”, the stylesheet:

.loaded{
    transition: opacity 1s ease-in-out;
    -webkit-transition: opacity 1s ease-in-out;
    -moz-transition: opacity 1s ease-in-out;
}

This way, you see “Loading” for 1sec, while everything is getting ready.

Questions:
Answers:

Since none of these answers gave me the desired result, I accomplished what I wanted by creating a directive very similar to ng-cloak but wrapping the code in a $timeout so that it will wait until the end of the $digest cycle to remove the cloaking attribute and/or class. This was the only way I was able to truly hide the {{}} bindings in the browser.

angular.directive('myCloak', function($timeout) {
  return {
    restrict: 'A',
    compile: function (element, attr) {
      $timeout(function () {
        attr.$set('myCloak', undefined);
        element.removeClass('my-cloak');
      });
    }
  };
});

And don’t forget, you will have to add a custom css rule for this new attribute / class:

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

Questions:
Answers:

Using the fix recommended here works for me…

https://github.com/opitzconsulting/jquery-mobile-angular-adapter/issues/167

CSS:

.my-cloak {
  display: none  !important;
}

JS:

$scope.$on('$viewContentLoaded', function(){
    $('.my-cloak').removeClass('my-cloak');
});

HTML:

div(class="my-cloak")

Questions:
Answers:

Use ngBind when ng-cloak is not available.

<p ng-show="!isShow" ng-bind="isShow"></p>