julius_am
julius_am

Reputation: 1527

angular watch on object and it's child

I have an on object in my directive, let's say:

scope = {
    A : { 
       B : [],
       C : 5
    }
}

scope.$watch('A', function aWasChanged(){});
scope.$watchCollection('B', function bWasChanged(){});

I have a watch on A and on B. But when A is changed the watch of B is called as well. What I want is that when A is changed only "aWasChanged" will be called (even if B was changed as well) and "bWasChanged" will be called only when B is changed.

Upvotes: 1

Views: 484

Answers (2)

hassassin
hassassin

Reputation: 5054

If you really wanted to do something like

$scope.foo.A = {
  B: [],
  C: 6
};

and have the watch on A fire but not on the B fire, you could always hack how angular is indexing it.

var key = $scope.foo.A.B.$$hashKey;
$scope.foo.A = {
  B: [],
  C: 6
};
$scope.foo.A.B.$$hashKey = key;

Here is an updated plnkr with that http://plnkr.co/edit/hAY9pb3AUAF0drAm42A5?p=preview.

Upvotes: 0

Maxim Shoustin
Maxim Shoustin

Reputation: 77904

What do you mean under A is changed.

Generally the $watch() only checks object reference equality but not structure.

For example if you will write something like:

$scope.A.ddd = "ddd";

the $watch will do not catch that.

However deep-watch (with flag true) should take care about this case.

when A is changed only "aWasChanged" will be called...

I suppose you mean if C will change ... so write your custom comparator like:

$scope.$watch(function () {
       return $scope.A;
    },
    function (newValue, oldValue) {

     if(newValue.C == oldValue.C){return;} // avoid B

     /*...*/

    }, true); // Object equality (not just reference).

The deep-watch a bit expensive so like you wrote will be good way:

scope.$watchCollection('A.B', function bWasChanged(){});

Upvotes: 1

Related Questions