0
votes

Question about "scope" in angularJS I try to show a loading animation when i do a search.

In my controller i create a var called "loader" and in the HTML i put ng-show="loader" on the div that i would like to show/hide

Simple... But...

I can show the loader but can't hide it...

Here is my code...

HTML :

 <secion ng-controller="ContactsCtrl">
    <div class="loader" ng-show="loading"></div>

    <h2>Contacts</h2>

    <form class="form-search">
        <input type="text" ng-model="s_search" placeholder="Search for a contact...">
        <button type="submit" class="btn" ng-click="search()">Search</button>    
    </form>

    <div id="resultContact"></div>

</section>

JS :

function ContactsCtrl($scope){
    $scope.loading = false;

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

    $scope.search = function() {
        $scope.loading = true;

        setTimeout($scope.endLoading, 1000);
    }
}

I suppose the problem is with the "scope inherits" but i don't see my mistake

2

2 Answers

5
votes

You need to call $scope.$apply() whenever you call Angular outside of Angular (e.g. jQuery event handlers or, here, setTimeout()). But the best way is to use the Angular service, $timeout (docs) that does the same job and calls $apply.

1
votes

setTimeout is outside the digest cycle of Angular. You need to use $timeout to alert angular about your function.

function ContactsCtrl($scope, $timeout){
    $scope.loading = false;

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

    $scope.search = function() {
        $scope.loading = true;

        $timeout($scope.endLoading, 1000);
    }
}

I would like to point out that it seems like you're doing some kind of "loading", which implies using $http or other data lookup. Instead of setting a timer, you could tie a function to the completion event, or set a watcher on the data that changes.

For example:

$scope.$watch("searchData", function () {
  $scope.loading = false;
}, true);


$scope.$search = function () {
  $scope.loading = true;

  $http.get("/searchUrl", function (res) {
    $scope.searchData = res;
  });
});