patorjk
patorjk

Reputation: 2182

AngularJS's $scope.watch function is not firing on data modification

You can see the problem in this plunk with Chrome or FireFox's console open:

http://plnkr.co/edit/jmDcxqQ48PmeHt3EPVMU

When you click "Push!" for the first time, the watch function doesn't execute. But if you push it again, it does execute. It's like it ignores the first push. However, you can clearly see the dataPoints array changes after the first push due to the timeout function that is executing in the background. What's weirder, is if you comment out the jQuery fadeIn wrapper, the code works as expected (the watch function is executed on the first button push).

What's going on here? Why is the $watch function not executing when jQuery().fadeIn is used?

Upvotes: 0

Views: 993

Answers (1)

Mark Rajcok
Mark Rajcok

Reputation: 364727

jQuery('#mytest').fadeIn(200, function() {
    $scope.mydata.dataPoints.push(1);
    $scope.$$phase || $scope.$apply();
})

When the fadeIn callback runs, it runs "outside" Angular, so we need to call $scope.$apply() to run a digest cycle. However, if the object is already visible, it seems that jQuery runs the callback immediately (so we're still "inside" Angular), so we don't need to (and shouldn't) call $scope.$apply().

The easy way to handle both cases is to check to see if we are already in a digest cycle using private property $$phase. A cleaner implementation would be to not call fadeIn() if the div is already visible.

Upvotes: 2

Related Questions