Angularjs - Hide content until loading DOM

I have a problem in Angularjs where there is flicker in my HTML before my data comes back from the server.

Here is a video demonstrating the problem: http://youtu.be/husTG3dMFOM - pay attention to # | and the gray area on the right.

I tried ngCloak without any success (although ngCloak does not allow parentheses to appear as promised), and I am wondering what is the best way to hide content until the HTML is filled with Angular.

I got it to work with this code in the controller:

var caseCtrl = function($scope, $http, $routeParams) { $('#caseWrap').hide(); // hides when triggered using jQuery var id = $routeParams.caseId; $http({method: 'GET', url: '/v1/cases/' + id}). success(function(data, status, headers, config) { $scope.caseData = data; $('#caseWrap').show(); // shows using jQuery after server returns data }). error(function(data, status, headers, config) { console.log('getCase Error', arguments); }); } 

... but I heard again and again not to manipulate the DOM from the controller. My question is: how can I achieve this using the directive? In other words, how can I hide the element to which the directive is attached until all the content is downloaded from the server?

+49
angularjs
Aug 08 '13 at 18:24
source share
6 answers

In CSS add:

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

and just add the ng-cloak "attribute to your div, like here:

 <div id="template1" ng-cloak>{{scoped_var}}<div> 

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

+109
Aug 30 '14 at 21:30
source share

On your caseWrap element, type ng-show="contentLoaded" and then where you have $('#caseWrap').show(); put $scope.contentLoaded = true;

If the caseWrap element is outside this controller, you can do the same using $ rootScope or events .

+9
Aug 08 '13 at 18:34
source share

Add the following to your CSS:

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

Compiling your angular templates is not fast enough.

UPDATE

You should not manipulate the DOM in the controller. There are two things you can do ... 1. You can intercept changes in value within the scope of the controller through the directive! In your case, create a directive as an attribute that is assigned the property that you want to see. In your case, it will be caseData . If casedata is false, hide it. Otherwise, show it.

  1. The easiest way is to use ngShow = 'casedata'.

the code

 var myApp = angular.module('myApp', []); myApp.controller("caseCtrl", function ($scope, $http, $routeParams, $timeout) { $scope.caseData = null; //mimic a delay in getting the data from $http $timeout(function () { $scope.caseData = 'hey!'; }, 1000); }) .directive('showHide', function () { return { link: function (scope, element, attributes, controller) { scope.$watch(attributes.showHide, function (v) { if (v) { element.show(); } else { element.hide(); } }); } }; }); 

HTML

 <div ng-controller='caseCtrl' show-hide='caseData'>using directive</div> <div ng-controller='caseCtrl' ng-show='caseData'>using ngShow</div> 

JSFIDDLE: http://jsfiddle.net/mac1175/zzwBS/

+7
Aug 08 '13 at 18:28
source share

Since you asked for a directive, try this.

 .directive('showOnLoad', function() { return { restrict: 'A', link: function($scope,elem,attrs) { elem.hide(); $scope.$on('show', function() { elem.show(); }); } } }); 

Stick to (show-on-load) in your element, and in your controller, enter $ rootScope and use this broadcast event when loading html.

 $rootScope.$broadcast('show'); 
+2
Aug 08
source share

I used Zack's answer to create a 'loading' directive that may be useful to some people.

Template:

 <script id="ll-loading.html" type="text/ng-template"> <div layout='column' layout-align='center center'> <md-progress-circular md-mode="indeterminate" value="" md-diameter="52"></md-progress-circular> </div> </script> 

Directive:

  directives.directive('loading', function() { return { restrict: 'E', template: 'll-loading.html', link: function($scope,elem,attrs) { elem.show(); $scope.$on('loaded', function() { console.log("loaded: "); elem.hide(); }); } } }); 

This example uses the angular material in html

+1
Dec 22 '15 at 16:52
source share

The accepted answer did not help me. I had some elements that had ng-show directives, and the elements would still display for a moment, even with ng-cloak. It looks like ng-cloak was allowed before ng-show false. Adding the ng-hide class to my elements fixed my problem.

0
Mar 28 '16 at 21:06
source share



All Articles