Angular 2 life cycle hook after all children are initialized?
I ended up using the ngAfterViewInit() hook in the following way:
ngAfterViewInit(){
//stuff that doesn't do view changes
setTimeout(_=> this.methodThatKicksOffAnotherRoundOfChanges());
}
This should be safe to use compared to other invocations of setTimeout where an actual time is set, since it should start instantly (and just affect the threading/context behaviour)
If you need your Parent Component to await custom asynchronous behaviour across multiple child components then here's a good solution I cooked up.
Any child component's that initialise asynchronously extend this:
import {Subject} from 'rxjs/Subject';
import {Observable} from 'rxjs/Observable';
export class AsynchronouslyInitialisedComponent {
loadedState: Subject<boolean> = new Subject<boolean>();
loadedState$ = this.loadedState.asObservable();
constructor() {
}
protected componentLoaded() {
this.loadedState.next(true);
}
}
Example Child component:
import {Component} from '@angular/core';
import {AsynchronouslyInitialisedComponent} from './../base_component';
@Component({
moduleId: module.id,
selector: 'child'
})
export class Child extends AsynchronouslyInitialisedComponent {
constructor() {
super();
}
ngOnInit() {
//Some async behavoir:
setTimeout(() => {
this.componentLoaded();
}, 10000);
}
}
Now all your Parent component needs to do is the following:
import {Component, ViewEncapsulation, ViewChild};
import {Observable} from 'rxjs/Observable';
import 'rxjs/add/observable/zip';
@Component({
moduleId: module.id,
selector: 'parent'
})
export class Parent {
@ViewChild('child') child; //Just use <child #child></child> in your template
constructor() {
}
ngOnInit() {
Observable
.zip(this.child.loadedState$, this.otherChild.loadedState$) //Add as many as you want here...
.subscribe(pair => {
console.log('All child components loaded');
});
}
}
If you also have content children (transcluded using <ng-content>
) then ngAfterContentInit()
is the right lifecycle callback.
https://angular.io/docs/ts/latest/guide/lifecycle-hooks.html#!#aftercontent
ngAfterContentInit() {
doSomething();
}
Make the child components emit an event on their Init and listen for it where you need it