Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why angular 2 ngOnChanges not responding to input array push

My angular application stuck with a issue, i used input as array and pushed a value to the array when the click event arise. But the ngOnChanges not firing when the array push is done. Is there a way to fire ngOnChange

My Code is ts file is

@Component({
  selector: 'adv-search',
  templateUrl: './app/modules/result.html'
})

export class InputComponent {
  @Input() metas:any=[];

  ngOnChanges() {
    console.log(this.metas);
  }
}

My Selector Tag

<adv-search [metas] = "metaIds"></adv-search>

Click Event Code

insertIds(id:any) {
   metaIds.push(id);
}
like image 502
Manush Avatar asked Apr 05 '17 06:04

Manush


People also ask

Why ngOnChanges is not getting called?

ngOnChanges gets called before ngOnInit and whenever a component's bound input is changed FROM THE PARENT COMPONENT. Remember that ngOnChanges is specific to bound inputs on the component. This means if you don't have any @Input properties on a child, ngOnChanges will never get called.

How does ngOnChanges work in angular?

The ngOnChnages is a life cycle hook, which angular fires when it detects changes to data-bound input property. This method receives a SimpeChanges object, which contains the current and previous property values. The child Component decorates the property using the @Input decorator.

What is difference between ngOnChanges and ngDoCheck?

ngOnChanges() ( OnChanges ) is called when a value bound to an input has changed so you can run custom code when an input has changed. ngDoCheck() ( DoCheck ) is called when change detection runs so you can implement your custom change detection action.

Does ngOnChanges run on init?

With this update, ngOnChanges immediately fires. It also fires upon initialization of input data. The hook receives one optional parameter of type SimpleChanges . This value contains information on the changed input-bound properties.


3 Answers

Angular change detection only checks object identity, not object content. Inserts or removals are therefore not detected.

What you can do is to copy the array after each update

insertIds(id:any) {
  this.metaIds.push(id);
  this.metaIds = this.metaIds.slice();
}

or use IterableDiffer to check for changes inside InputComponent in ngDoCheck like NgFor does.

like image 127
Günter Zöchbauer Avatar answered Oct 21 '22 02:10

Günter Zöchbauer


If you reassign your metaIds array, the ngOnChanges lifecycle event will be fired. You can deconstruct your array into a new array.

insertIds(id:any){
    this.metaIds = [...this.metaIds, id];
}
like image 30
KyleGill Avatar answered Oct 21 '22 02:10

KyleGill


@GünterZöchbauer 's answer is completely correct. However, I would like to add a alternative/supplement to copying the whole array. Using the same example from the question.

<adv-search [metas] = "metaIds"></adv-search>

altered to

<adv-search [metas] = "{trackBy: metaIds.length, metaIds: metaIds}"></adv-search>

Where length here is the equivalent of the *ngFor trackBy function for the component. With this the ngOnChanges occurs with content length changes.

If used in combination with the *ngFor trackBy method there should be some performance benefits as the whole array's bound templates are not recalculated (no screen/content flickering).

like image 10
JerradPatch Avatar answered Oct 21 '22 02:10

JerradPatch