How to prevent element show before AngularJS initialized( ng-show )
Asked Answered
P

6

17

In AngularJS, I wonder how to prevent the elements shown on page before ng-show take effect, I found some posts talk about ng-cloak, but it seems not work in my case, probably the ng-cloak is for prevent double curly bracket rather than Element style.

Another way someone talk about is define some style for before AngularJS initialized, but that is kinda hard to manage.

Is there some official way to handle this?

Perpetua answered 27/6, 2015 at 0:37 Comment(1)
The correct way to do this is to show a loader while you load if it gas any delay... that's just good ux. I have given you the solution to show a loader while the loading/rendering occurs. If you don't want loader us ngcloak as suggested. The loader I gave you does not use a timeout either to do this which is a correct approach. Please accept the answer if not works for you ;)Pulchia
F
25

Unless you want to show a loader, ng-cloak should be your solution.

Official documentation on ng-cloak

If you still have the issue, you may try to add the css to hide element with ng-cloak inside your html to be sure the browser has it in time.

If you do that, choose on way to add the ng-cloak. For example add it as class:

<div ng-show="condition" class="ng-cloak">...</div>

And add this into your html head tag:

<style> .ng-cloak { display: none !important; } </style>
Fritz answered 27/6, 2015 at 1:22 Comment(1)
Just beware that whatever is cloaked/hidden on the page, it's still there. If you use ui-router, the HTML is only injected at the right time. Another alternative is ng-bind e.g. <span ng-bind="expression_without_braces"></span>Lowboy
C
4

In case you want to just avoid showing something till it's ready to be shown (some data has been loaded from the backend perhaps) then it's better to use ng-if. Ofcourse it works the same with ng-show. But the advantage of using ng-if is that you delay the creation of the extra DOM until it needs to be shown and as a result you improve the intial page loading time.

Here is an example:

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


   
myApp.controller("myController", function ($scope, $timeout) {

    $scope.isLoading = false;
    $scope.data = null;
    
    simAsync();

    //simulate async task like http request
    function simAsync() {
        //loadind data has started
        $scope.isLoading = true;

        $timeout(function () {
            $scope.data = [{
                "firstname": "Sims",
                    "lastname": "Wilkerson"
            }, {
                "firstname": "Kelli",
                    "lastname": "Vazquez"
            }, {
                "firstname": "Mcdonald",
                    "lastname": "Byrd"
            }, {
                "firstname": "Taylor",
                    "lastname": "Frost"
            }, {
                "firstname": "Merle",
                    "lastname": "Adkins"
            }, {
                "firstname": "Garrett",
                    "lastname": "Hood"
            }];
            //the data has loaded
            $scope.isLoading = false;
        }, 1500);
    }

});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="myController">
    
</div>
Cardinalate answered 27/6, 2015 at 7:17 Comment(1)
ng-if won't work (it's content will be shown) if the HTML is on the index page & angular isn't ready yet.Lowboy
L
2

2 alternatives to completely avoid the problem:

<span ng-bind="expression_without_braces"></span>

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

  • use ui-router to keep HTML in separate files, which will be loaded/parsed/injected only when needed and only when the controller is initialized.

Here's the hello world tutorial modified to use a separate HTML file:

// helloworld.js
var myApp = angular.module('helloworld', ['ui.router']);

myApp.config(function($stateProvider) {
  var helloState = {
    name: 'hello',
    url: '/hello',
    templateUrl: 'helloworld.html'
  }

  $stateProvider.state(helloState);
});
<!-- helloworld.html -->
<h3>hello world!</h3>
<!-- index.html -->
<html>
  <head>
    <script src="lib/angular.js"></script>
    <script src="lib/angular-ui-router.js"></script>
    <script src="helloworld.js"></script>
  </head>

  <body ng-app="helloworld">
    <a ui-sref="hello" ui-sref-active="active">Hello</a>

    <ui-view></ui-view>
  </body>
</html>
Lowboy answered 16/11, 2018 at 11:26 Comment(0)
P
1

Use a loader such as this:

JS

 angular.element(document).ready(function(){
      $('.loading').remove(); // Just an example dont modify the dom outside of a directive in a real app!
      alert('Loaded!'); 
    });

CSS

.loading {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: #fff;
  color: #000;
}

DEMO

http://codepen.io/nicholasabrams/pen/MwOMNR

I just answered a similar topic here: Angularjs tab Loading spinner while rendering

Pulchia answered 27/6, 2015 at 0:46 Comment(0)
W
1

Angular now supports ng-cloak. It is already defined as a class and also as a directive:

I use it like this as a directive:

    <div ng-show="condition" ng-cloak>...</div>

You can also use it like this as a class:

   <div ng-show="condition" class="ng-cloak">...</div>
Workbag answered 6/10, 2020 at 16:34 Comment(0)
M
1

just use attribute ng-cloak on init your AngularJs controller in serverside template

<div class="right_col col-md-9" role="main" data-ng-controller="SearchController as v"
 ng-init="v.init('<?= $catalog['id'] ?>')" ng-cloak>
Minium answered 6/4, 2021 at 8:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.