1

I have this very simple template:

{{ polygonDotsCount }}

And this code on controller:

$scope.polygonDotsCount = 0;
$scope.polygonClick = function() {
    $scope.polygonDotsCount = $scope.polygonDotsCount + 1;
    console.log($scope.polygonDotsCount);
};

polygonClick gets called everytime I click on a map, and I see the number increasing in the console, but the number is not increasing on the template! What could possibly be wrong with this?

4
  • 1
    Please include all the relevant code, including the HTML. With just this code, this problem cannot be reproduced. Commented Jun 5, 2015 at 19:46
  • Is {{polygonDotsCount}} inside the same controller as the function where you increment it? Provide a jsfiddle. Commented Jun 5, 2015 at 19:46
  • you need provide more data: codepen.io/luarmr/pen/Qbvybd it works with your code. Are you using ng-click right? Commented Jun 5, 2015 at 19:50
  • Mmm... I'm not using ng-click, and it's quite a complex piece of code to put all in a jsfiddle, as it uses 2 external scripts as well (Google Maps and a modified version of the-di-lab.com/polygon) there must be something wrong between all of them... ok, I found a solution, posting it right now Commented Jun 5, 2015 at 19:56

3 Answers 3

1

As you are updating a scope variable polygonDotsCount on click of google map event, the code will run but the changed scope variable never get updated on html. because digest cycle doesn't get run. In order update all binding digest cycle must have have. If you are doing any operation inside the angular context will apply digest cycle properly & will update the binding on html. But when you run any event like onclick or external events like you were using google map event that will never run the digest cycle. You need to run it manually in this case.

When to run $apply

For running digest cycle manually you need to call $apply() method of scope that will run $digest() method and update all the bindings. but directly calling $apply() to run digest cycle would cause an issue, because you sometime it happens while you run digest cycle & if there is already digest cycle running currently then it will throw an error that $digest is already in progress

So better you should use $timeout,

What $timeout does?

It actually run a digest cycle, but it has one advantage. While you wrote a code in $timeout function it will get executed & will run digest cycle. But while running that digest cycle the previous running digest is in progress then it wait till that digest cycle over & then execute after completion of that digest it will run its own digest cycle.

Code

$scope.polygonDotsCount = 0;
$scope.polygonClick = function() {
    $timeout(function(){ //<-- inject $timeout on controller before using it.
         $scope.polygonDotsCount = $scope.polygonDotsCount + 1;
         console.log($scope.polygonDotsCount);
    });
};

Using $timeout will ensure that it will never conflict with other running digest cycle

Sign up to request clarification or add additional context in comments.

Comments

0

Ok, it seems to be a problem with using different non-angular libraries. I'm using Google Maps and a modified version of the-di-lab.com/polygon

For some reason even though I see the scope being updated on the console, the HTML doesn't update, so I'm forcing the update with this function:

$scope.safeApply = function(fn) {
    var phase = this.$root.$$phase;
    if(phase == '$apply' || phase == '$digest') {
        if(fn && (typeof(fn) === 'function')) {
            fn();
        }
    } else {
        this.$apply(fn);
    }
};

If anyone can give an explanation of why this happens and a better way to solve it, I'll chose their answer.

Comments

0

This problem is related to digest cycle.

If AngularJS usually wraps our code in $apply() and starts a $digest cycle, then when do you need to do call $apply() manually? Actually, AngularJS makes one thing pretty clear. It will account for only those model changes which are done inside AngularJS’ context (i.e. the code that changes models is wrapped inside $apply()). Angular’s built-in directives already do this so that any model changes you make are reflected in the view. However, if you change any model outside of the Angular context, then you need to inform Angular of the changes by calling $apply() manually. It’s like telling Angular that you are changing some models and it should fire the watchers so that your changes propagate properly.

For details refer to "http://www.sitepoint.com/understanding-angulars-apply-digest/"

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.