All the components and directives have a lifecycle to angular components and directives creates, update, and destroy. We can implement the lifecycle hook interface and use the respective method to tap into any lifecycle moments. Components have more lifecycle hooks than directives.
All Angular lifecycle hooks
- OnInit
- OnChanges
- DoCheck
- AfterContentInit
- AfterCpntentChecked
- AfterViewInit
- AfterViewChecked
- OnDestroy
Note: Constructor is not a Lifecycle hook. Its typescript feature
Common lifecycle hooks methods
These general lifecycle hooks available for component and directive
- OnInit
- DoCheck
- OnChange
- OnDestroy
Lifecycle hooks only available in components
- AfterContentInit
- AfterContentChecked
- AfterViewInit
- AfterViewChecked
All angular lifecycle hooks methods
ngOnInit | This hook will call after the constructor is executed. if OnChanges was implemented, then it will call after ngOnChanges methods executed |
ngOnChanges | Call once before ngOnInit methods and when an input/output binding value changes |
ngDoCheck | Called immediately after ngOnChanges on every change detection run, and immediately after ngOnInit on the first run |
ngAfterContentInit | Called once after the first ngDoCheck |
ngAfterContentChecked | Called after ngAfterContentInit and every subsequent ngDoCheck |
ngAfterViewInit | Called once after the first ngAfterContentChecked |
ngAfterViewChecked | Called after the ngAfterViewInit and every subsequent ngAfterContentChecked |
ngOnDestroy | This hook will call before components destroy |
How to implement angular hooks?
- Add to implement hooks interface in component or directive class.
- Define particular hooks methods.
Create structure for example to better undertanding
I will generate a new project. it will contain parent and child components. So I will build this structure? when I explain these hooks, I will show code examples and screenshots to understand what’s happening.
generate project
ng new angular-lifecyle-hooks cd angular-lifecyle-hooks
Parent component
Generate parent component
ng g c parent
Render parent component in app.component.html file
<app-parent></app-parent>
Child component
Generate child component
ng g c child
Render child component in the parent component. Define child selector inside parent.component.html file
<p>This parent Element</p> <hr> <app-child></app-child>
#1 OnInit
OnInit hook provides ngOnInit methods for components or directives to handle any additional initialization tasks. ngOnInit will be invoked when the component has initialized. This hook method will be called only once after the ngOnChanges methods execute, If the OnChanges hook does not implement in the component then it will call after the constructor is executed. Mostly, We use ngOnInit for doing the initialization.
When we create a component using Angular CLI, we can see the OnInit hook has been implemented. But we can do it manually.
Use case example
Implement User list API call
import { HttpClient } from '@angular/common/http'; import { Component, OnInit } from '@angular/core'; @Component({ selector: 'app-parent', templateUrl: './parent.component.html', styleUrls: ['./parent.component.scss'] }) export class ParentComponent implements OnInit { userList: any constructor(private http: HttpClient) { console.log('Parent constructor is called') } ngOnInit(): void { console.log('Parent ngOnInit is called') this.getUserList() } getUserList(): void { this.http.get('https://jsonplaceholder.typicode.com/users').subscribe((data) => { this.userList = data; console.log(this.userList) }) } }
Here are console logs
#2 OnChanges
OnChanges hook provides ngOnChanges method for component and directive. ngOnChanges will be called once After the constructor is executed and It will be called whenever the data-bound @Input
properties changes. it’s not normal HTML input. It’s angular data-binding input.
ngOnChanges can pass the one argument interface of SimpleChanges
. When a component is first to run, this argument contains all the list of @Input. But when the single @Input change this argument contain changed @Input.
Let’s see example:
Edit parent.component.ts file.
Define searchInput and anotherInput properties in parent.component.ts file.
// ... export class ParentComponent implements OnInit { searchInput: any; anotherInput: any; constructor(private http: HttpClient) { console.log('Parent constructor is called') } // ... }
In parent.component.html file
<p>This parent Element</p> <input type="text" [(ngModel)]="searchInput" placeholder="Parent Input" /> <hr> <app-child *ngIf="showChild" [searchInput]="searchInput" [anotherInput]="anotherInput"></app-child>
In child.component.ts file
import { Component, Input, OnChanges, OnInit, SimpleChanges } from '@angular/core'; @Component({ selector: 'app-child', templateUrl: './child.component.html', styleUrls: ['./child.component.scss'] }) export class ChildComponent implements OnInit, OnChanges { @Input() searchInput!: string; @Input() anotherInput!: string constructor() { console.log('Child constructor is called') } ngOnInit(): void { console.log('Child ngOnInit is called') } ngOnChanges(changes: SimpleChanges): void { console.log('Child OnChanges'), console.log('Simple Changes', changes) } }
#3 DoCheck
DoCheck
will be invoked when the change detector of the given is invoked. It is called immediately after ngOnChanges
methods on every change detection run, and immediately after ngOnInit
on the first run.
import { Component, DoCheck, OnInit } from '@angular/core'; @Component({ selector: 'app-parent', templateUrl: './parent.component.html', styleUrls: ['./parent.component.scss'] }) export class ParentComponent implements OnInit, DoCheck { constructor(private http: HttpClient) { console.log('Parent constructor is called') } ngOnInit(): void { console.log('Parent ngOnInit is called') } ngDoCheck(): void { console.log('Parent ngDoCheck') } }
Note *: We should avoid using ngOnChanges and ngDoCheck in the same component. Sometimes, the change detection triggers another change and it became an infinite loop
Content projection Example for component lifecycle hook
Before start only available component hooks explanation. I need to create the content projection. Assume I wanted to send project some content to the child component from the parent component. let’s implement content projection
Send project from parent component
In the parent.component.html file. Create projection content and I select projection content with projectedContent
name.
<!-- other content --> <app-child [searchInput]="searchInput"> <!-- Projection content --> <div #projectedContent>Hello, this is project from parent</div> </app-child>
Show output in child component
In the child.component.html file. I added <ng-content>
an element where I want the projected content to appear.
<!-- content project render here --> <ng-content></ng-content>
Now select projection content
In the child.component.ts file. I can access the template ref variable with a build-in ContentChild selector.
import { Component, OnInit, ContentChild, ElementRef } from '@angular/core'; @Component({ selector: 'app-child', templateUrl: './child.component.html', styleUrls: ['./child.component.scss'] }) export class ChildComponent implements OnInit { @ContentChild('projectedContent') projectedContent!: ElementRef; // ... constructor() { console.log('Child constructor is called') } ngOnInit(): void { console.log('Child ngOnInit is called') } // ... }
#4 AfterContentInit
AfterContentInit hook methods ngAfterContentInit will be called only once after the first ngDoCheck.
I need to add the AfterContentInit hook in the component class as implements. In this example, I will console.log our projection content (#projectedContent) in ngOnInit and ngAfterContentInit.
Edit child.component.ts file
import { AfterContentInit, Component, ContentChild, ElementRef, Input, OnInit } from '@angular/core'; @Component({ selector: 'app-child', templateUrl: './child.component.html', styleUrls: ['./child.component.scss'] }) export class ChildComponent implements OnInit, OnChanges, AfterContentInit, OnDestroy { @Input() searchInput!: string; @ContentChild('projectedContent') projectedContent!: ElementRef; constructor() { console.log('Child constructor is called') } ngOnInit(): void { console.log('Child ngOnInit is called') console.log('OnInit content', this.projectedContent) } ngAfterContentInit(): void { console.log('Child after content init') console.log('AfterContentInit content', this.projectedContent) } }
Result preview
You can see ngOnInit methods content undefined, But ngAfterContentInit method can select projection content as a Angular native element.
#5 AfterContentChecked
ngAfterContentChecked will be called after ngAfterContentInit and every subsequent ngDoCheck’
Let’s implement ngAfterContentChecked example
import { AfterContentChecked, AfterContentInit, Component, ContentChild, ElementRef, Input, OnChanges, OnDestroy, OnInit, SimpleChanges } from '@angular/core'; @Component({ selector: 'app-child', templateUrl: './child.component.html', styleUrls: ['./child.component.scss'] }) export class ChildComponent implements OnInit, AfterContentInit, AfterContentChecked { @Input() searchInput!: string; @ContentChild('projectedContent') projectedContent!: ElementRef; constructor() { console.log('Child constructor is called') } ngOnInit(): void { console.log('Child ngOnInit is called') console.log('OnInit content', this.projectedContent) } ngAfterContentInit(): void { console.log('Child AfterContentInit') console.log('AfterContentInit content', this.projectedContent) } ngAfterContentChecked(): void { console.log('Child AfterContentChecked') } }
Preview
#6 AfterViewInit
ngAfterViewInit will be called once after the first ngAfterContentChecked
// ... export class ChildComponent implements OnInit, AfterContentInit, AfterContentChecked, AfterViewInit, AfterViewChecked { // ... ngAfterViewInit(): void { console.log('Child AfterViewInit') } }
#7 AfterViewChecked
ngAfterViewChecked will be called after ngAfterViewIint and every subsequent ngAfterContentChecked
// ... export class ChildComponent implements AfterViewChecked { // ... ngAfterViewChecked(): void { console.log('Child AfterViewChecked') } }
#8 OnDestroy
OnDestroy will be called one just before the component is removed from the DOM, in other words when the component is destroyed from the DOM.
OnDestroy is used for any custom cleanup. And this hook is primarily used to unsubscribe from our observable streams and to disconnect event handlers to avoid memory leaks.
how to use onDestroy Hook?
The components or directives class implements the OnDestroy interface. OnDestiry hook interface provide ngOnDestroy() method.
... @Component({ ... }) export class ParentComponent implements OnDestroy { constructor(private http: HttpClient) { console.log('Parent constructor is called') } ngOnDestroy(): void { console.log('Parent OnDestroy is called') } }
Source: https://angular.io/guide/lifecycle-hooks
Example Source Code: https://github.com/techincent/angular-lifecycle-hooks.git