How to use a $watchGroup with object equality or d

2019-01-23 05:00发布

问题:

I want a directive to re-render HTML whenever three scope variables have changed. The first two are just integers, the third is an array.

We have $watchGroup to watch several variables, we have $watch with objectEquality as a third parameter, and we have $watchCollection which is like $watch, but with objectEquality implied.

Is there a way to write a $watch similar to this?

$scope.$watchGroup(['number1', 'number2', 'myArray'], callback, true); // true for objectEquality

回答1:

Well it seems like watchGroup does not support a deep watch. So probably you can do a hack, by registering an anonymous deep watcher with array of values being passed in from the watch function.

$scope.$watch(function(){
     return ['number1','number2','myArray'].map(angular.bind($scope, $scope.$eval));
  }, function(newV){
      console.log(newV);
  },true);

Demo

or just add this function as utility function on the rootScope and access it from any inherited scopes.

.run(function($rootScope){
  $rootScope.deepWatchGroup = function(exp, callback){
    if(!angular.isArray(exp) || !thisScope.$watch) return; //Or log some error if array is not passed in or the context is not really a scope object

   var thisScope = this, //get scope
        evalFunc = angular.bind(thisScope, thisScope.$eval); //and a bound eval func

     thisScope.$watch(function(){
        return exp.map(evalFunc); //return array of evaluated values
     }, callback,true);
   }
});

and from your controller do:

$scope.deepWatchGroup(['number1','number2','myArray'],function(newV){
  console.log(newV);
});

Demo



回答2:

If you want to watch an array of string expressions (i.e. you do not need to watch functions, which both $watchGroup and PSL's solution can handle), here is an alternative:

$scope.$watch('[number1, number2, myArray]', callback, true);

And if you want to make a utility function for that similar to PSL's:

.run(function($rootScope){
  $rootScope.deepWatchGroup = function(watchExpressions, listener){
    this.$watch('[' + watchExpressions + ']', listener, true);
  }
});


回答3:

I also had the same problem as yours.

My solution to this deep watchgroup problem is:

// Create new object to watch different types of objects
var objectToBeWatch = {
    number1: number1, 
    number2: number2,
    myArray: myArray
};

$scope.$watch(
    function () {
        return objectToBeWatch;
}, callback, true);

I hope this helps!