2

is there a lifecycle hook so-called "ngAfterAllChildrenInit" because ngAfterViewInit is called before ngOninit of the children,

I am trying to avoid hacking with setTimeOut or emitting events from all the children and collecting them and then do what I want ( that depend on the children initialization)

it seems so common why is it not part of angular?

Shaul Naim
  • 246
  • 3
  • 15

3 Answers3

1

You could use decorators for that. I mean, Angular decorators, not custom ones.

In your parent :

activated: any = {};

In your children :

constructor(@Host() parent: ParentComponent) {}

// Hook of your choice
ngOnInit() { this.parent.activated[this.constructor.name] = true; }

This will create an activated object like this

activated = {
  FirstChildComponent: true
  // Second not initialized ? Then not here and activated[SecondChildComponent] = undefined
};
0

Angular Lifecycle hooks are very powerful, in order to achieve what you want, you can simply use the OnInit lifecycle hook. Angular is reading your template file and running your component in a vertical way (from top to down). So, you just have to do whatever you want in your last component's ngOnInit method.

If your components are used in different parts of your application, you can check that the parent component is the one you want by using the @Host decorator (see the answer of @trichetriche).

I created a stack blitz where there's 3 components used in the app component (parent) in this order:

<hello name="{{ name }}"></hello>
<app-child></app-child>

So the AppComponent OnInit hook will fire first, and after that the HelloComponent OnInit and finally the ChildComponent.

See it in action on the console: https://stackblitz.com/edit/angular-62xjux

EDIT: You can use the ngAfterViewChecked as the documentation specifies:

Respond after Angular checks the component's views and child views / the view that a directive is in.

Called after the ngAfterViewInit and every subsequent ngAfterContentChecked().

Mehdi Benmoha
  • 3,694
  • 3
  • 23
  • 43
  • This is a very contextual answer. Your exampl works because your components are useless : they contain no code, no logic, nothing. What happens if there is a huge component, and a very tiny one ? They won't launch in the same order. You can't rely on the fact that they will be launched one after the other, this is too fragile ! –  Mar 14 '18 at 10:22
  • This is only intialization ! You can use another lifecycle hook if you want to be sure that the components has rendered, for example `ngAfterViewChecked` – Mehdi Benmoha Mar 14 '18 at 10:37
  • 1
    Same argument applies. If one has a much bigger view and the other has just a div, nothing guarantees the order. –  Mar 14 '18 at 10:38
  • I tried, ngAfterViewChecked gets fired every time Angular checks the view if it needs updates. So it gets fired very often, and after a few cycles it also runs into the view update error – Shaul Naim Mar 14 '18 at 14:28
0

how about use a service. the last child publish an event through observable, and the parent subscribes to it.

tigerpaw
  • 135
  • 4