10

I have this code inside an angular directive, and I'm finding the $watch behavior a bit confusing. The updateSelect is called in an "ng-click":

scope.updateSelect = function (type) {
    scope.selectionCtrl.activeList = scope.seedLists[type]; 
    scope.selectionCtrl.activeListKey = type; 
    scope.selectionCtrl.activeSelection = scope.selection[type];
    scope.selectionCtrl.staged = [];
    scope.selectionCtrl.stageRemove = [];
    if (type !== scope.activeTab) {
        scope.activeTab = type;
    }
    console.log("update");
};

scope.$watch('selectionCtrl.activeList', function(newValue, oldValue) {
    console.log("watch");
}, true);

When I click on the button (triggering updateSelect), and watch the console, I see "update" and then "watch". The first thing that happens inside the function is selectionCtrl.activeList is set, so I would expect to see "watch" and then "update".

Shouldn't watch trigger as soon as the array has changed?

3
  • 3
    The function has to finish first as javascript is single threaded Commented Nov 14, 2014 at 18:35
  • I see, so if selectionCtrl.activeList is binded to an ng-repeat, then the ng-repeat won't actually update until the end of updateSelect, is that right? Commented Nov 14, 2014 at 18:38
  • You should add that as an answer, thanks Gruff Commented Nov 14, 2014 at 18:41

3 Answers 3

2

The function has to finish first as javascript is single threaded.

Because the function was called via the ng-click directive, angular will run a digest cycle. Part of that digest cycle is to run through the watch list and resolve all the changes that may have occurred since the cycle last ran.

In the example you give, selectionCtrl.activeList is changed in updateSelect which subsequently results in the watch callback being called.

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

Comments

1

When does Angular execute watch callback?

It's related to $digest and $apply, and certainly it does not execute within your raw javascript code.

To make watch execute forcefully, you can run $scope.apply() manually, but may cause more problem and not necessary if it is within a angularjs function, i.e. $timeout, $interval, etc, because it will be called automatically after the function.

For more info., lookup;

Comments

-1

https://docs.angularjs.org/api/ng/type/$rootScope.Scope :

The watchExpression is called on every call to $digest() and should return the value that will be watched. (Since $digest() reruns when it detects changes the watchExpression can execute multiple times per $digest() and should be idempotent.)

If you try i.e.:

scope.selectionCtrl.activeList = scope.seedLists[type]; 
scope.$digest();

you'll get Error: [$rootScope:inprog] $apply already in progress.

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.