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
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
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!
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);
}
});