0

I'm having an array of blog posts on my controller and each time I'm updating the array I want the view to change accordingly.

This is the partial html (The only thing that relevant is that I'm using ng-repeat):

<div ng-repeat="blog in blogCtrl.blogs">
    <blog author="blog.author" title="blog.title" content="blog.content"></blog>    
    <button ng-click="blogCtrl.like(blog._id)" class="btn btn-info glyphicon glyphicon-thumbs-up">{{blog.likes}}</button>
    <button ng-click="blogCtrl.remove()" class="btn btn-danger glyphicon glyphicon-remove"></button>
</div>

This is my controller:

like(blogId){
        this.BlogsDao.like(blogId).then(response => {
            // replacing the old blog with the updated one
            this.$scope.$apply(function(){
                var itemIndex = _.findIndex(this.blogs, function(item){
                    return item._id === blogId;
                });
                this.blogs.splice(itemIndex, 1, response.data); 
            });

        });
    }

Now when I'm clicking on the like button which triggers the like function on my controller.

console output is:

Error: [$rootScope:inprog] $digest already in progress
http://errors.angularjs.org/1.4.5/$rootScope/inprog?p0=%24digest
    at REGEX_STRING_REGEXP (angular.js:68)
    at beginPhase (angular.js:16235)
    at Scope.parent.$get.Scope.$apply (angular.js:15976)
    at blogs.ctrl.js:22
    at processQueue (angular.js:14634)
    at angular.js:14650
    at Scope.parent.$get.Scope.$eval (angular.js:15878)
    at Scope.parent.$get.Scope.$digest (angular.js:15689)
    at Scope.parent.$get.Scope.$apply (angular.js:15986)
    at done (angular.js:10511)

I was searching for the solution on other posts, but although there are many posts on this issue, no one gave my a clue on what is happening here.

What am I doing wrong?

Shikloshi
  • 3,761
  • 7
  • 32
  • 58
  • 2
    Why do you even need a `$scope.$apply` in your controller? Shouldn't AngularJS update it automatically? – DanEEStar Sep 15 '15 at 10:41
  • As a matter of fact you are right. Tried it again without $apply and ng-repeat was modified accordingly. Thanks! – Shikloshi Sep 15 '15 at 10:45

1 Answers1

0

You can check if a $digest is already in progress by checking $scope.$$phase.

Try this

  if(!$scope.$$phase) {
       this.$scope.$apply(function(){
                    var itemIndex = _.findIndex(this.blogs, function(item){
                        return item._id === blogId;
                    });
                    this.blogs.splice(itemIndex, 1, response.data); 
                });

    }

More details, Please checkout this discussions : AngularJS : Prevent error $digest already in progress when calling $scope.$apply()

Community
  • 1
  • 1
Ramesh Rajendran
  • 37,412
  • 45
  • 153
  • 234
  • 1
    its antipattern https://github.com/angular/angular.js/wiki/Anti-Patterns , you could add a note..or prefer to use `$timeout` – Pankaj Parkar Sep 15 '15 at 10:49