AngularJS : watching a particular property in an array of objects for changes in the property's value

Array of Objects:

$scope.toppings = [
   { topping: 1, bits: 2, name: 'onions' },
   { topping: 2, bits: 4, name: 'mushrooms' },
   { topping: 3, bits: 8, name: 'peppers', checked:undefined /*may be*/ }
];

Watch using AngularJs $WatchCollection:

Instead of monitoring objects array above, that can change for any property in the object, we will create an array of properties of the elements for which we are watching the collection (.checked).

We filter the array's elements to only monitor those elements which have .checked defined and map that to an array for angular watchCollection.

When a change fires, I will compare the old and new arrays of (.checked) to get exact changed element using lodash difference method.

 $scope.$watchCollection(

                // Watch Function
                () => (
                   $scope
                     .toppings
                     .filter(tp => tp.checked !== undefined)
                     .map(tp => tp.checked)
                 ),

                // Listener
                (nv, ov) => {
                    // nothing changed
                    if(nv == ov || nv == "undefined") return;

                    // Use lodash library to get the changed obj
                    let changedTop = _.difference(nv,ov)[0];
                
                    // Here you go..
                    console.log("changed Topping", changedTop);
            })

You use MAP to collect all of the property values you need + convert them into a small string representation (in this case 1 and 0) and then join them together into a string that can be observed.

A typescript example:

        $scope.$watch(
            () => this.someArray.map(x => x.selected ? "1" : "0").join(""),
            (newValue, oldValue, scope) => this.onSelectionChanged(this.getSelectedItems()));