How to $scope.$watch
multiple variables in Angular, and trigger callback when one of them has changed.
$scope.name = ... $scope.age = ... $scope.$watch('???',function(){ //called when name or age changed })
When you have to trigger events like callback etc on multiple objects using $watch you can use methods like $watchGroup and $watchCollection. Since Angular 1.3 Angular offers two scope methods $watchGroup and $watchCollection. An example of using $watchGroup is given below.
The ng-repeat directive repeats a set of HTML, a given number of times. The set of HTML will be repeated once per item in a collection. The collection must be an array or an object. Note: Each instance of the repetition is given its own scope, which consist of the current item.
The ng-repeat-start directive works the same as ng-repeat, but will repeat all the HTML code (including the tag it's defined on) up to and including the ending HTML tag where ng-repeat-end is placed.
In angularjs $watch() function is used to watch the changes of variables in $scope object. Generally the $watch() function will create internally in angularjs to handle variable changes in application.
UPDATE
Angular offers now the two scope methods $watchGroup (since 1.3) and $watchCollection. Those have been mentioned by @blazemonger and @kargold.
This should work independent of the types and values:
$scope.$watch('[age,name]', function () { ... }, true);
You have to set the third parameter to true in this case.
The string concatenation 'age + name'
will fail in a case like this:
<button ng-init="age=42;name='foo'" ng-click="age=4;name='2foo'">click</button>
Before the user clicks the button the watched value would be 42foo
(42
+ foo
) and after the click 42foo
(4
+ 2foo
). So the watch function would not be called. So better use an array expression if you cannot ensure, that such a case will not appear.
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <link href="//cdn.jsdelivr.net/jasmine/1.3.1/jasmine.css" rel="stylesheet" /> <script src="//cdn.jsdelivr.net/jasmine/1.3.1/jasmine.js"></script> <script src="//cdn.jsdelivr.net/jasmine/1.3.1/jasmine-html.js"></script> <script src="http://code.angularjs.org/1.2.0-rc.2/angular.js"></script> <script src="http://code.angularjs.org/1.2.0-rc.2/angular-mocks.js"></script> <script> angular.module('demo', []).controller('MainCtrl', function ($scope) { $scope.firstWatchFunctionCounter = 0; $scope.secondWatchFunctionCounter = 0; $scope.$watch('[age, name]', function () { $scope.firstWatchFunctionCounter++; }, true); $scope.$watch('age + name', function () { $scope.secondWatchFunctionCounter++; }); }); describe('Demo module', function () { beforeEach(module('demo')); describe('MainCtrl', function () { it('watch function should increment a counter', inject(function ($controller, $rootScope) { var scope = $rootScope.$new(); scope.age = 42; scope.name = 'foo'; var ctrl = $controller('MainCtrl', { '$scope': scope }); scope.$digest(); expect(scope.firstWatchFunctionCounter).toBe(1); expect(scope.secondWatchFunctionCounter).toBe(1); scope.age = 4; scope.name = '2foo'; scope.$digest(); expect(scope.firstWatchFunctionCounter).toBe(2); expect(scope.secondWatchFunctionCounter).toBe(2); // This will fail! })); }); }); (function () { var jasmineEnv = jasmine.getEnv(); var htmlReporter = new jasmine.HtmlReporter(); jasmineEnv.addReporter(htmlReporter); jasmineEnv.specFilter = function (spec) { return htmlReporter.specFilter(spec); }; var currentWindowOnload = window.onload; window.onload = function() { if (currentWindowOnload) { currentWindowOnload(); } execJasmine(); }; function execJasmine() { jasmineEnv.execute(); } })(); </script> </head> <body></body> </html>
http://plnkr.co/edit/2DwCOftQTltWFbEDiDlA?p=preview
PS:
As stated by @reblace in a comment, it is of course possible to access the values:
$scope.$watch('[age,name]', function (newValue, oldValue) { var newAge = newValue[0]; var newName = newValue[1]; var oldAge = oldValue[0]; var oldName = oldValue[1]; }, true);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With