[javascript] Watch multiple $scope attributes

Is there a way to subscribe to events on multiple objects using $watch

E.g.

$scope.$watch('item1, item2', function () { });

This question is related to javascript angularjs events angularjs-watch

The answer is


Why not simply wrap it in a forEach?

angular.forEach(['a', 'b', 'c'], function (key) {
  scope.$watch(key, function (v) {
    changed();
  });
});

It's about the same overhead as providing a function for the combined value, without actually having to worry about the value composition.


how about:

scope.$watch(function() { 
   return { 
      a: thing-one, 
      b: thing-two, 
      c: red-fish, 
      d: blue-fish 
   }; 
}, listener...);

$watch first parameter can be angular expression or function. See documentation on $scope.$watch. It contains a lot of useful info about how $watch method works: when watchExpression is called, how angular compares results, etc.


Angular introduced $watchGroup in version 1.3 using which we can watch multiple variables, with a single $watchGroup block $watchGroup takes array as first parameter in which we can include all of our variables to watch.

$scope.$watchGroup(['var1','var2'],function(newVals,oldVals){
   console.log("new value of var1 = " newVals[0]);
   console.log("new value of var2 = " newVals[1]);
   console.log("old value of var1 = " oldVals[0]);
   console.log("old value of var2 = " oldVals[1]);
});

Beginning with AngularJS 1.1.4 you can use $watchCollection:

$scope.$watchCollection('[item1, item2]', function(newValues, oldValues){
    // do stuff here
    // newValues and oldValues contain the new and respectively old value
    // of the observed collection array
});

Plunker example here

Documentation here


A slightly safer solution to combine values might be to use the following as your $watch function:

function() { return angular.toJson([item1, item2]) }

or

$scope.$watch(
  function() {
    return angular.toJson([item1, item2]);
  },
  function() {
    // Stuff to do after either value changes
  });

$watch first parameter can also be a function.

$scope.$watch(function watchBothItems() {
  return itemsCombinedValue();
}, function whenItemsChange() {
  //stuff
});

If your two combined values are simple, the first parameter is just an angular expression normally. For example, firstName and lastName:

$scope.$watch('firstName + lastName', function() {
  //stuff
});

You can use functions in $watchGroup to select fields of an object in scope.

        $scope.$watchGroup(
        [function () { return _this.$scope.ViewModel.Monitor1Scale; },   
         function () { return _this.$scope.ViewModel.Monitor2Scale; }],  
         function (newVal, oldVal, scope) 
         {
             if (newVal != oldVal) {
                 _this.updateMonitorScales();
             }
         });

$scope.$watch('age + name', function () {
  //called when name or age changed
});

Here function will get called when both age and name value get changed.


Here's a solution very similar to your original pseudo-code that actually works:

$scope.$watch('[item1, item2] | json', function () { });

EDIT: Okay, I think this is even better:

$scope.$watch('[item1, item2]', function () { }, true);

Basically we're skipping the json step, which seemed dumb to begin with, but it wasn't working without it. They key is the often omitted 3rd parameter which turns on object equality as opposed to reference equality. Then the comparisons between our created array objects actually work right.


Examples related to javascript

need to add a class to an element How to make a variable accessible outside a function? Hide Signs that Meteor.js was Used How to create a showdown.js markdown extension Please help me convert this script to a simple image slider Highlight Anchor Links when user manually scrolls? Summing radio input values How to execute an action before close metro app WinJS javascript, for loop defines a dynamic variable name Getting all files in directory with ajax

Examples related to angularjs

AngularJs directive not updating another directive's scope ERROR in Cannot find module 'node-sass' CORS: credentials mode is 'include' CORS error :Request header field Authorization is not allowed by Access-Control-Allow-Headers in preflight response WebSocket connection failed: Error during WebSocket handshake: Unexpected response code: 400 Print Html template in Angular 2 (ng-print in Angular 2) $http.get(...).success is not a function Angular 1.6.0: "Possibly unhandled rejection" error Find object by its property in array of objects with AngularJS way Error: Cannot invoke an expression whose type lacks a call signature

Examples related to events

onKeyDown event not working on divs in React Detect click outside Angular component Angular 2 Hover event Global Events in Angular How to fire an event when v-model changes? Passing string parameter in JavaScript function Capture close event on Bootstrap Modal AngularJs event to call after content is loaded Remove All Event Listeners of Specific Type Jquery .on('scroll') not firing the event while scrolling

Examples related to angularjs-watch

Watch multiple $scope attributes