Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to $watch multiple variable change in angular [duplicate]

Tags:

angularjs

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 }) 
like image 518
aztack Avatar asked May 24 '13 07:05

aztack


People also ask

How to watch multiple variables in AngularJS?

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.

How does ng-repeat work?

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.

What is ng-repeat end?

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.

What is $Watch in angular?

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.


1 Answers


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); 
like image 126
stofl Avatar answered Sep 29 '22 10:09

stofl