Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular.js doesn't refresh the repeater after $scope.var changes but only after refresh

I thought 2 ways binding was angular thing:

I can post from a form to the controller, and if I refresh the page I see my input on the page:

$scope.loadInput = function () {

    $scope.me.getList('api') //Restangular - this part works
    .then(function(userinput) {

        $scope.Input = $scope.Input.concat(userinput);
        // scope.input is being referenced by ng-repeater in the page 
        // so after here a refresh should be triggered.

    },function(response){
        /*@alon TODO: better error handling than console.log..*/
        console.log('Error with response:', response.status);
    });
};

In the html page the ng-repeater iterates over the array of for i in input. but the new input from the form isn't shown unless I refresh the page.

I'll be glad for help with this - thanks!

like image 932
alonisser Avatar asked Oct 22 '13 11:10

alonisser


1 Answers

Try $scope.$apply:

$scope.loadInput = function () {
        $scope.me.getList('api') //Restangular - this part works
        .then(function(userinput) {
               $scope.$apply(function(){ //let angular know the changes

                $scope.Input = $scope.Input.concat(userinput);
             });

            },function(response){
                /*@alon TODO: better error handling than console.log..*/
                console.log('Error with response:', response.status);
            });
    };

The reason why: Your ajax is async, it will execute in the next turn, but at this time, you already leaves angular cycle. Angular is not aware of the changes, we have to use $scope.$apply here to enter angular cycle. This case is a little bit different from using services from angular like $http, when you use $http service and handle your response inside .success, angular is aware of the changes.

DEMO that does not work. You would notice that the first click does not refresh the view.

setTimeout(function(){
             $scope.checkboxes = $scope.checkboxes.concat([{"text": "text10", checked:true}]);
         },1);

DEMO that works by using $scope.$apply

setTimeout(function(){
            $scope.$apply(function(){
         $scope.checkboxes = $scope.checkboxes.concat([{"text": "text10", checked:true}]);
            });
        },1);
like image 171
Khanh TO Avatar answered Sep 27 '22 22:09

Khanh TO