Question

I cannot figure out why my simple AngularJS app not working as intended. "Loading..." is supposed to be hidden, and "Done!" should be shown after 1 second.

html:

<div ng-app>
    <div ng-controller="TestCtrl">
        <div class="text-center" ng-show="loading">
            <h1>Loading...</h1>

    </div>
        <div class="text-center" ng-show="!loading">
            <h1>Done!</h1>

        </div>
    </div>
</div>

Javascript:

function TestCtrl($scope) {
    $scope.loading = true;
    setTimeout(function () {
        $scope.loading = false;
    }, 1000);
}
Was it helpful?

Solution

You need to tell angular that you updated the var:

function TestCtrl($scope) {
    $scope.loading = true;
    setTimeout(function () {
        $scope.$apply(function(){
            $scope.loading = false;
        });
    }, 1000);
}

or just

function TestCtrl($scope, $timeout) {
    $scope.loading = true;
    $timeout(function () {
        $scope.loading = false;
    }, 1000);
}

OTHER TIPS

A nicer way of doing this is by calling $scope.$digest(); to update your UI

You need to use $timeout and inject it in your controller:

function TestCtrl($scope, $timeout) {
    $scope.loading = true;
    $timeout(function () {
        $scope.loading = false;
    }, 1000);
}

Fiddle demo

Edit: removed $scope.apply(); as @Salman suggested

You want to use apply() function to stop loading message.

Check this Demo jsFiddle**.

JavaScript:

function TestCtrl($scope) {
    $scope.loading = true;
    setTimeout(function () {
        $scope.$apply(function(){
            $scope.loading = false;
        });
    }, 1000);
}

Hope this would be help you!

when fire angular event to another object like setTimeout you should use

$scope.$apply(function(){
     $scope.loading = false;
});

for example

var loading={
     show:function(){
        $scope.loading=true
     },
     hide:function(){
        $scope.loading=false
     }
}  

may not working best way

   var loading={
         show:function(){
            $scope.$apply(function(){
               $scope.loading=true
            });
         },
         hide:function(){
            $scope.$apply(function(){
               $scope.loading=false
            });
         }
    } 

I have found that one way to work around ng-show not evaluating in the way you want it to be is to use ng-class instead.

 <div class="mycontent" data-ng-class="{'loaded': !loading}"> 

This way when $scope.loading is not equal to true the css class 'loaded' will be added to the element. Then you just need a to use the css class to show/hide the content.

.mycontent {
    display: none;
}

.loaded {
    display: block;
}

I think the biggest problem here is that you are using a primitive as your model. The angular team recommends to use an object to tie your model to. For example:

scope.model = {};
scope.model.loading = false;

Then in your html:

<div class="text-center" ng-show="model.loading">

That way angular gets a reference to a field inside an object instead of a primitive being pointed to by a variable.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top