How to Detect Changes to an Input Array from a Child Component in Angular


Detecting changes to an array from the @Input() directive can be tricky.

Suppose we have the following input array arr that is bound to a getter and setter.

_arr: string[] = [];
get arr(): string[] {
    return this._arr;
}
@Input() set arr(newArr: string[]) {
    this._arr = newArr;
}

Properties Passed by Reference

Let’s say we have a Child component that accepts an arr and contains the getters and setters from above.

<Child [arr]='arr'></Child>

We’d expect arr to update in the Child component if we pushed to this array, but this isn’t the case. Properties that are passed by reference will not trigger the setter of this @Input() directive. This includes mutating an object as well.

In these scenarios, we would need to update the reference passed as an input in order to trigger the setter.

Solution

We can create a new reference by merging our array with an empty array.

this.arr = ['corgi', 'shih tzu'];
this.arr.push('pug');
this.arr = [].concat(this.arr);

This solution is a constant time operation since we are simply creating a new variable that points to the same area in memory as the previous one. We aren’t cloning the contents of the array.

This means our reference changes, thereby triggering the OnChanges mechanism in the Child component.