angular watch object
by Max Kovalov
HTML
<div class='test' ng-app="app" ng-controller="TestWatch">
prop1: {{prop1}} <br>
prop2: {{prop2}} <br>
prop3 (unwatched): {{prop3}} <br>
<button ng-click="test1()">
Simple props change
</button>
<button ng-click="test2()">
Async props change
</button>
<button ng-click="test3()">
Async props change with apply
</button>
</div>
JavaScript
// TEST app code
var app = angular.module('app', ['watch_utils']);
app.controller('TestWatch', ['$scope', 'TestService', 'WatchObj', TestWatchCtrl]);
function TestWatchCtrl($scope, testService, watch){
$scope.prop1 = testService.prop1;
$scope.prop2 = testService.prop2;
$scope.prop3 = testService.prop3;
watch(testService, ['prop1', 'prop2'], $scope, $scope);
$scope.test1 = function(){
testService.test1();
};
$scope.test2 = function(){
testService.test2();
};
$scope.test3 = function(){
testService.test3();
};
}
app.service('TestService', ['apply', TestService]);
function TestService(apply){
this.apply = apply;
this.reset();
}
TestService.prototype.reset = function(){
this.prop1 = 'unchenged';
this.prop2 = 'unchenged2';
this.prop3 = 'unchenged3';
}
TestService.prototype.test1 = function(){
this.prop1 = 'changed_test_1';
this.prop2 = 'changed2_test_1';
this.prop3 = 'changed3_test_1';
}
TestService.prototype.test2 = function(){
setTimeout(function(){
this.prop1 = 'changed_test_2';
this.prop2 = 'changed2_test_2';
this.prop3 = 'changed3_test_2';
}.bind(this));
}
TestService.prototype.test3 = function(){
setTimeout(function(){
this.prop1 = 'changed_test_3';
this.prop2 = 'changed2_test_3';
this.prop3 = 'changed3_test_3';
this.apply();
}.bind(this));
}
//END TEST APP CODE
//WATCH UTILS
var mod = angular.module('watch_utils', []);
mod.service('apply', ['$timeout', ApplyService]);
function ApplyService($timeout){
return function apply(){
$timeout(function(){});
};
}
mod.service('WatchObj', ['$rootScope', WatchObjService]);
function WatchObjService($rootScope){
// target not always equals $scope, for example when using bindToController syntax in directives
return function watch_obj(obj, fields, target, $scope){
// if $scope is not provided, $rootScope is used
$scope = $scope || $rootScope;
var watched = fields.map(function(field){
return...