Consider this plunker
Note: To observe the effect you have to rerun the app after the entering the link
import {Component, OnInit, Input, OnChanges, DoCheck} from 'angular2/core' @Component({ selector: 'sub', template: ` <li *ngFor="#elem of sub_list"> <div>{{elem['name']}}</div> </li> ` }) export class Sub { @Input() sub_list: Object[]; ngOnInit(){ console.log('init'); console.log(this.sub_list); } ngOnChanges(){ console.log('change'); console.log(this.sub_list); } ngDoCheck() { console.log('check'); console.log(this.sub_list); } } @Component({ selector: 'my-app', template: ` <div> <sub [sub_list]="my_list" > </sub> </div> `, directives: [Sub] }) export class App { my_list: Object[] = []; ngOnInit() { var vm = this; setTimeout(function() { for(var i = 0; i < 100; i++) { vm.my_list.push({ 'index' : i, 'name' : i }); } }, 100); } }
If I try to print out this.sub_list
in Sub
‘s ngOnChange
the browser outputs an empty list.
However we can see that ngDoCheck
still correctly captures the change.
Is there a specific reason for this?
Advertisement
Answer
In your case ngOnChanges won’t be called for updates on the array. As a matter of fact, Angular2 detects updates based on references. I mean if the reference of the whole array doesn’t change (it’s the case when adding an element in it using the push method), the ngOnChanges method won’t be called.
In your case your array is null when ngOnChanges is called because it’s called before the input element is set.
There are two ways to detect changes in this case:
update the whole array reference using methods like slice (after the push) or concat.
this.myArray.push({...}); this.myArray.push = this.myArray.push.slice();
leverage the ngDoCheck method with the IterableDiffers class to manually check updates. The class allows you to register callbacks to be notified when an element is added (or remove) in an array.
See these links for more details: