Angular 2 how to make child component wait for async data to be ready
Solution 1:
There are three ways to do this:
- Put an
*ngIf
in parent. Only render child when parent'sitems
is ready.
<div *ngIf="items">
<child [items]="items | async">
</div>
- Separate your input
getter
setter
in child. Then act whenever the value is set, you can use RxJSBehaviorSubject
also.
private _items = new BehaviorSubject<Items[]>([]);
@Input() set items(value: Items[]) {
this._items.next(value);
}
get items() {
return this._items.getValue();
}
ngOnInit() {
this._items.subscribe(x => {
this.chunk(x);
})
}
- Do it during the
ngOnChanges
of the child. Refer to here for example. https://angular.io/docs/ts/latest/guide/lifecycle-hooks.html#!#onchanges
Solution 2:
Simpler solution:
ngOnChanges(changes: SimpleChanges) {
if (changes['items'].currentValue) {
this.items = items
}
}
Solution 3:
You can use a setter :
export class child implements OnInit{
itemChunks: Items[][];
private _items ;
//bellow will get called when ever the items are passed in by the parent component
@Input( 'items' ) set items ( items: Items[] ) {
this._items = items;
this.itemChunks = this.chunk(this._items);
}
chunk(items: Items[]) {
let result = [];
for (var i = 0, len = items.length; i < len; i += 6) { // this line causes the problem since 'items' is undefined
result.push(items.slice(i, i + 6));
}
return result;
}
}
Any by the way, I feel like your parent component is not right as well, it should be :
@Component({
moduleId: module.id,
selector: 'parent',
template: `<div>
<child [items]="items | async">
</div>`
})
export class Parent implements OnInit {
items: Items[];
constructor(
private itemService: ItemService,
private router: Router
) {
this.items = this.itemService.getItemss(); // if getItemss is returning an observable, which I think it does
}
}