ngOnChanges not firing if an @Input is receiving an object

亡梦爱人 提交于 2019-12-09 01:38:16

问题


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?


回答1:


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




回答2:


The OnChanges lifecycle hook is triggered when the @Input property value changes. In the case of an object, that value is the object reference. If the object reference does not change, OnChanges is not triggered.

A possible technique to force change detection is to set a new object reference after modifying the property values:

this.whatever.value1 = 2;
this.whatever.value2 = 3;
this.whatever = Object.assign({}, this.whatever);

The ngOnChanges event handler can then be used to monitor the changes:

ngOnChanges(changes: SimpleChanges) {
  for (let propName in changes) {
    let chng = changes[propName];
    let cur = JSON.stringify(chng.currentValue);
    console.log(propName, cur);
  }
}

As an alternative, if @Input decorates a getter/setter property, the changes can be monitored in the setter:

private _param: Object;

@Input() get param(): Object {
  return this._param;
} 
set param(value: Object) {
  console.log("setter", value);
  this._param = value;
}

See this stackblitz for a demo.




回答3:


Like this:

@Input() public param: any;
ngOnChanges(changes: SimpleChanges): void {
    // Do your check here
    console.log(changes.param.previousValue);
}

Using changes gets you access to previousValue and currentValue.



来源:https://stackoverflow.com/questions/55050015/ngonchanges-not-firing-if-an-input-is-receiving-an-object

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!