I am trying to understand exactly what causes the
AfterContentInit() life-cycle hooks to fire.
From the Official Angular Documentation it says for AfterViewInit()
Angular calls after it creates a component’s child views
and it says for AfterContentInit()
Angular calls after Angular projects external content into the component
These two statements already seem nearly indistinguishable to me. Isn’t a child view the same as external content?
Take for example:
<div class="parent"> <child-comp></child-comp> </div>
Where child-comp is a child component that contains a lot of markup and is dependent on asynchronous data.
In the parent.component.ts I want to wait until the child component is completely rendered before calling either
AfterContentInit(). When I run this code it happens in the exact sequence Angular says it will
AfterContentInit() is called first followed by
AfterViewInit(). Currently the child-comp isn’t receiving a lot of data, but eventually it could and it will take longer to render (the data will grow once live).
What I fear is right now since my data is limited and load times are so fast by choosing one life-cycle hook over the other I may be unwillingly end up in a race condition – that will fail once data increases and load times decelerate.
This starts to make more sense if you’ve began some dynamic component loading or manual view creation in Angular.
OnInit is called once when the component’s
@Outputs have been resolved.
AfterViewInit is called when the component’s view has been attached. Remember that Angular compiles all views to JS files, not html – the framework manages templates in code and has a rendering engine to interact with the DOM. In addition to actually rendering components, Angular needs to recursively build and manage child/parent relationships in regard to component bindings and their lifetime cycles. Child components will also need their bindings resolved and to go through the same rendering lifecycle as their parents. Simply put, at this hook
@ViewChildren will be resolved — child components will be fully initialized, and their properties will be available.
AfterContentInit is a little weirder. It’s called when the component’s child views and external content have been attached. This comes from content projection, normally into
<ng-content> tags. It’s another step the renderer needs to take going down the tree, resolving all projected content before attaching it to the disjointed view. You really don’t need to worry about it if you’re not messing around with templates or
@ContentChildren will be resolved.
As for the race condition you mentioned, there is no need to worry if you are using the right lifecycle hook for what’s needed — they’re just hooks called immediately after
@ContentChildren have been set on the component — race conditions for injected properties shouldn’t exist through the inversion of control to change detection (non-framework factors nonwithstanding) 🙂