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()));