Search code examples
angularangular6angular2-template

ngOnChanges not firing if an @Input is receiving an object


Parent component template:

<my-component [param]="whatever"></my-component>

Parent component code:

whatever = { value1: 0, value2: 1, value3: 'foo' };

Child component code:

@Input() public param: any;

ngOnChanges() {
  console.log('Received input: ', param);
}

This isn't working. Any change to whatever will be unnoticed by the child component and ngOnChanges won't fire.

It also doesn't work if I try to use a setter:

@Input() set param(value) {
  console.log(value);
}

And it doesn't help if I try to run a manual zone update in the parent component.

Apparently @Input() can only detect when an object's structure has changed, but not its values.

So how can I pass an object as an @Input() property and have the child component detect value changes?


Solution

  • Angular change detection is triggered when the @Input property value changes.

    So to trigger change detection in case of an object you could pass a copy of the object using spread operator as the input.

    for eg. someVar = {key: value} this is @Input() variable, so pass like

    <app-sample [someVar]="{...someVar}" ></app-sample>
    

    {...VARIABLE} <- here is the magic

    if spread operator won't work use any object deep copying methods like

    JSON.parse(JSON.stringify(obj))