In this article, I am going to explain component’s lifecycle hooks. I have already explained first three hooks ( i.e., OnChange, OnInit and DoCheck) in my previous article Component Lifecycle Hooks in Angular 5.
Let’s start with the remaining hooks.
ngAfterContentInit()
This is called whenever the content which is projected through ng-content has been initialized, so not the view of the component itself but instead, we can say, the view of the parent component (especially a part of the parent) is added to our component.
Here, content projected means a way to import HTML content from outside the component and insert that content into the content’s template in a designated spot and this spot is identified by Angular with the help of <ng-content>, i.e. it can put the content’s template where <ng-content></ng-content> is present.
Let’s understand this with an example.
Create one more component called “second” using the below command.
ng g c second
Now, let us go to second.component.html file and put the following lines.
- <br>
- Title :- {{title}}
- <br>
Go to second.component.ts file, and set the value of title.
- title: string;
- constructor() {
- this.title = "Hello Mahesh!";
- }
Go to app.component.ts file.
- @Component({
- selector: 'after-content',
- template: `
- <div class="row">
- <div class="col-md-4">
- <div class="card">
- <div class="card-header bg-primary text-white"> ngAfterContentInit () </div>
- <div class="card-body">
- <div>
- <input type="text" />
- <ng-content></ng-content><br>
- </div>
- </div>
- </div>
- </div>
- </div>`,
- })
-
- export class AfterContent implements AfterContentInit{
-
- @ContentChild(SecondComponent) contentChild: SecondComponent;
- ngAfterContentInit() {
- console.log("After content in it");
- }
-
- }
-
- @Component({
- selector: 'app-root',
- template: `<div>
- <after-content>
- <app-second></app-second>
- </after-content>
- </div>`,
- styleUrls: ['./app.component.css']
- })
-
- export class AppComponent {
-
- title = 'app';
- valueFromChild: any;
- }
In the above code, we created one more component called "AfterContent" and made it as a parent component for second component. In the aftercontent component, inside the template, we put <ng-content></ng-content> where child content, i.e., the second component can be injected.
Whenever this child component is projected into parent component, it fires ngAfterContentInit(). When we run this code, we will see the following output.
Now, again my question is "what is the benefit of using this?"
So, the benefit is that if we want to change something after the content is loaded, then we can easily change it. For example - if we want to change the title, we change it inside the ngAfterContentInit() hook, like
- ngAfterContentInit() {
- this.contentChild.title = "my first title";
- console.log("After content in it");
- }
We have already set the title inside the constructor of second.component.ts file, like -
- constructor() {
- this.title = "Hello Mahesh!";
- }
So, the first constructor is invoked but after the content projection, the title will be changed due to ngAfterContentInit() and we will get the following output like,
ngAfterContentChecked()
It is executed whenever the change detection occurs i.e. content will be projecting into our component. It is called immediately after the ngAfterContentInit and after every subsequent ngDoCheck().
Let’s understand with an example.
We are going to create a button and on button click, we will change the value of “AfterContent”. So, whenever this value changes, ngAfterContentChecked() fires.
Go to second.component.html file,
- <br>
- Title :- {{title}}
- <br>
- <button class="btn btn-primary" (click)="onClick()">Change</button>
Write definition for onClick() method inside second.component.ts file
- onClick() {
- this.title = "Value Change";
- }
Now, go to app.component.ts file and implement ngAfterContentChecked() inside AfterContent Class, like
- export class AfterContent implements AfterContentInit, AfterContentChecked {
- ngAfterContentCheckedcalled = 0;
-
- @ContentChild(SecondComponent) contentChild: SecondComponent;
-
- ngAfterContentInit() {
- this.contentChild.title = "my first title";
- console.log("After content in it");
- }
-
- ngAfterContentChecked() {
- this.ngAfterContentCheckedcalled += 1;
- console.log("After content checked");
- }
- }
And inside the AfterContent’s template, display the value of ngAfterConetentCheckedCalled variable like,
- template: `
- <div class="row">
- <div class="col-md-4">
- <div class="card">
- <div class="card-header bg-primary text-white"> ngAfterContentInit () </div>
- <div class="card-body">
- <div>
- <input type="text" />
- <ng-content></ng-content><br>
- Value Changed : {{ngAfterContentCheckedcalled}}
- </div>
- </div>
- </div>
- </div>
- </div>`,
Now, we run into this program,
ngAfterViewInit()
It is called after the component's view (and child view) has been initialized. It is very similar to ngAfterContentInit, but it works on view that is whenever view is initialize it fires.
ngAfterViewChecked()
It fires after ngAfterViewInit() and every time the view (and child view) have been checked. This hook is fired after the ngAfterViewInit and after that for every subsequent ngAfterContentChecked hook.
As per the name it both will run with View i.e. whenever view (template) is initialized and if some changes occur.
For understanding the above two, just change into second.component.ts file, like:
- ngAfterViewInit(){
- console.log("After view init");
- }
-
- ngAfterViewChecked(){
- console.log("After value updated");
- }
ngOnDestroy()
This hook is called once the component or directive is about to destroy. Generally, we put logic related to cleanup here. This is the right place where we would like to Unsubscribe Observable and detach event handlers to avoid memory leaks.
Lets understand with example :
We go to second.component.html file, and write the following code:
- <br>
- Title :- {{title}}
- <br>
Go to second.component.ts file and write the following code, inside the class.
- constructor() {
- this.title = "Hello Mahesh!";
- }
-
- onClick() {
- this.title = "Value Change";
- }
-
- ngOnInit() {
- console.log('ChildComponent:OnInit');
- }
-
- ngOnDestroy() {
- console.log('ChildComponent:OnDestroy');
- }
Now, go to app.component.ts file and change the template as well as class, in template write the following code:
- @Component({
- selector: 'app-root',
- template: `<div class="row">
- <div class="col-md-4">
- <div class="card">
- <div class="card-header bg-primary text-white"> ngOnDestroy() </div>
- <div class="card-body">
- <div>
- <button (click)="toggle()">Hide/Show Child </button>
- <app-second *ngIf="displayChild"></app-second>
- </div>
- </div>
- </div>
- </div>
- </div>`,
- styleUrls: ['./app.component.css']
- })
And put the below code inside the class
- export class AppComponent {
- displayChild = true;
- constructor() {
- console.log('AppComponent:Constructor');
- }
- toggle() {
- this.displayChild = !this.displayChild;
- }
- ngOnInit() {
- console.log('AppComponent:OnInit');
- }
- ngOnDestroy() {
- console.log('AppComponent:OnDestroy');
- }
- }
See the below output:
In the above picture, when child component is projected into our parent’s component then as per our above code, first constructor of Parent’s component runs, after that ngOnInit() of Parent’s component runs, after that ngOnInit() of child’s component. We can see messages on console screen.
Now, the question is, how am I sure about that my child’s component can be projected into Parent’s component?
So, the answer is, press F12 for developer tool, go to the elements and see template of Second component (“<app-second>”) which is our child component that can be attached with DOM (look into picture).
Now, if we click on Hide/Show button, then it destroys the component or we can say detaches the component from parents component. But before the destruction it executes ngOnDestroy() hook and displays the message on the console screen and after that we are also not seeing “<app-second>” into elements tab inside the developer’s tools. Please look at the below picture
This is all about the Component’s life cycle hook with example. Now, at the end of the article I want to draw your attention that this cycle hook is changed a little bit when child’s component is created. Please have a look at the below picture
Conclusion
As we know, components are very important in Angular and as a developer, we should know about these hooks also. After reading this article, we can say that we have knowledge of life cycle hooks and what is the role of those hooks in Angular projects.
I attached a demo sample application “SampleLifeCycleHook” in my previous lifecycle hook i.e. on “Angular 5 – Lifecycle Hook”, this project contains the code related to all lifecycle hooks.