Component Life Cycle In Angular

Component Life Cycle In Angular

 In this article, we will learn how to use Angular lifecycle hooks. The life cycle hooks are the techniques that angular uses to generate, update, and destroy directives and components. We may fine-tune the behavior of our components during their creation, updating, and removal by using lifecycle hooks.

What are lifecycle hooks in Angular Components?

The root component is created and rendered when the angular application starts. It then generates and renders its children and their descendants. It forms a component tree.

Angular begins rendering the view after the components have been loaded. To do so, it must examine input properties, analyze data bindings and expressions, generate projected information, and so on. When a component is no longer required, Angular removes it from the DOM.

Angular uses lifecycle hooks to notify us when certain events occur.

Angular life cycle hooks are simply callback functions that Angular calls when a specific event occurs during the component's life cycle.

For example,

  • When Angular first initializes the component, it calls ngOnInit.
  • Angular calls ngOnChanges when the input property of a component changes.
  • Angular calls ngOnDestroy when a component is destroyed.


Lifecycle hooks in angular

The following is a list of all the life cycle hooks that angular uses during the component life cycle. When a specific event occurs, Angular calls them up.


The cycle of Change Detection

We must first comprehend the change detection cycle before moving on to the lifecycle hooks.

The process through which angular keeps the template in sync with the component is called change detection.

Consider the code below.

<div>Hello {{name}}</div>

When the value of the name changes, Angular updates the DOM. And it does so in a flash.

When the value of the name changes, how does angular know? It accomplishes this by performing a change detection cycle on every event that could lead to a change. It runs it on every change in the input, DOM events, timer events like setTimeout() and setInterval(), and http requests, among other things.

Angular compares each bound property in the template to that of the component class throughout the change detection cycle. It updates the DOM if it detects any changes.

During the critical stages of the change detection method, Angular raises the life cycle hooks.

Constructor

When Angular builds the component class, the component's life cycle begins. The class Constructor method is the first to be called.

Constructor isn't a life cycle hook, and it's also not unique to Angular. It's a feature of Javascript. It's a method that gets called when a new class is formed.

To inject dependencies, Angular uses a constructor.

None of the component's input properties are available at this time. Neither of its child components has been built. Also unavailable are projected contents.

As a result, you won't be able to achieve much with this strategy. It is also not advised to use it.

When Angular instantiates the class, it starts the component's first change detection cycle.

ngOnChanges

Angular calls the ngOnChanges life cycle hook whenever a component's or directive's data-bound input property changes. Angular's first task throughout the change detection cycle is to initialize the Input properties. It also raises the ngOnChanges hook whenever it detects any change in property. During each change detection cycle, it does so. If change detection fails to detect any changes, this hook is not raised.

The @Input decorator is used to declare properties that are used as inputs. It's one of the methods a parent uses to communicate with the kid component.

The child component declares the property message as the input property in the following example.
@Input() message:string

The data can be sent to the kid by the parent using the property binding method, as demonstrated below.
<app-child [message]="message">
</app-child>

The change detector looks to see if the parent component has altered the input properties of a component. If it is, the ngOnChanges hook is raised.

In the article How to pass data parent to a child component, we used this life cycle hook.

The change detector detects changes by using the stringent equality operator ===. As a result, for objects, the hook is only triggered when the references are modified. Why ngOnChanges does not fire has further information on it.

ngOnInit

After creating the component and updating its input properties, Angular raises the ngOnInit hook. After the ngOnChanges hook, it raises it.

This hook is only used once, and it is fired right after it is created (during the first change detection).

This is an excellent area to put any initialization logic for your component. You may access all of the component's input properties from here. You can use them in http get requests to receive data from the backend server or to perform some startup logic, for example.

However, at this time, neither the child components nor the expected content is available. As a result, any properties marked with @ViewChild, @ViewChildren, @ContentChild, and @ContentChildren will be unavailable for use.

ngDoCheck

During every change detection cycle, Angular calls the ngDoCheck hook event. This hook is called even if none of the properties have changed.

After the ngOnChanges and ngOnInit hooks, Angular calls it.

When Angular fails to detect changes to Input properties, use this hook to implement a custom change detection. When using the Onpush change detection approach, this hook is quite important.

The Angular ngOnChanges hook does not catch all of the input property changes.

ngAfterContentInit

After the Component's projected content has been fully initialized, the ngAfterContentInit life cycle hook is called. Before raising this hook, Angular additionally updates the properties decorated with the ContentChild and ContentChildren. Even if there is no content to project, this hook gets raised.

The external content injected from the parent component using Content Projection is referred to as "content."

The ng-content element in Angular Components can be used as a placeholder for content from the parent, as illustrated below.
<h2>Child Component</h2>
<ng-content></ng-content>   <!-- placehodler for content from parent -->

The content is injected between the opening and closing elements by Parent. This content is passed to the child component by Angular.
<h1>Parent Component</h1>
<app-child> This <b>content</b> is injected from parent</app-child>

Angular examines if the injected content has changed and updates the DOM throughout the change detection cycle.

This hook is just for components.

ngAfterContentChecked

ngAfterContentChecked is a life cycle hook that is invoked after Angular has finished inspecting the component's projected content during every change detection cycle. Before raising this hook, Angular additionally updates the properties decorated with the ContentChild and ContentChildren. Even if the component has no projected content, Angular calls this hook.

The ngAfterContentInit hook is pretty similar to this one. After the external content has been initialized, checked, and updated, both methods are invoked. The only difference is that after each change detection cycle, ngAfterContentChecked is raised. During the initial change detection cycle, ngAfterContentInit is used.

This hook is just for components.

ngAfterViewInit

After the Component's View and all of its child views have been fully initialized, the ngAfterViewInit hook is invoked. Before raising this hook, Angular additionally modifies the properties decorated with the ViewChild and ViewChildren properties.

The current component's template, as well as all of its child components and directives, are referred to as the View.

This hook is called when angular initializes the view for the first time during the first change detection cycle.

All lifecycle hook methods and change detection of all child components and directives are handled at this point, and the component is complete.

This hook is just for components.

ngAfterViewChecked

After checking and updating the component's views and child views, Angular fires this hook. This event is fired after ngAfterViewInit and every change detection cycle after that.

The ngAfterViewInit hook is pretty similar to this one. After all of the child components and directives have been initialized and modified, both are called. The only difference is that throughout each change detection cycle, ngAfterViewChecked is raised. ngAfterViewInit is called during the initial cycle of change detection.

ngOnDestroy

This hook is called shortly before Angular destroys the Component/Directive instance.

You can use this method to perform any cleanup logic for the component. To avoid memory leaks, you should Unsubscribe Observables and detach event handlers here.

How to Use Lifecycle Hooks

  • Hook interfaces for importing data
  • Declare Component/Directive to be true. Interface for lifecycle hooks is implemented.
  • Make a hook method.

Let's make a simple component that uses the ngOnInit hook.

Using Angular Cli, create an Angular project.

let's, Open the app.component.ts file.

Import Hook interfaces

Hook interfaces from the core module are imported. Hook name without ng is the name of the interface. OnInit, for example, is the interface of the ngOnInit hook.
import { Component,OnInit } from '@angular/core'

Component Implements lifecycle hook interface

After that, create an AppComponent to implement the OnInit interface.
export class AppComponent implements OnInit {

}

Create the hook method

The methods for the life cycle hook must have the same name as the hook.
ngOnInit() {
    console.log("AppComponent:OnInit");
}

The whole app.component.ts code.
import { Component,OnInit } from '@angular/core';
 
@Component({
  selector: 'app-root',
  template: `
      <h2>Life Cycle Hook</h2>` ,
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
  
  constructor() {
    console.log("AppComponent:Constructor");
  }
 
  ngOnInit() {
    console.log("AppComponent:OnInit");
  }
 
}

Open the developer console and run the code. You'll notice the following:
AppComponent:Constructor
AppComponent:OnInit

Note that the constructor event is fired before the OnInit hook.

The Order of Execution of Life Cycle Hooks

The hooks are executed in the following order by Angular.

Creating Components
  1. OnChanges
  2. OnInit
  3. DoCheck
  4. AfterContentInit
  5. AfterContentChecked
  6. AfterViewInit
  7. AfterViewChecked

When you make a component with a child component,
1. OnChanges
2. OnInit
3. DoCheck
4. AfterContentInit
5. AfterContentChecked
5.1 Child Component -> OnChanges
5.2 Child Component -> OnInit
5.3 Child Component -> DoCheck
5.4 Child Component -> AfterContentInit
5.5 Child Component -> AfterContentChecked
5.6 Child Component -> AfterViewInit
5.7 Child Component -> AfterViewChecked
6. AfterViewInit
7. AfterViewChecked

After you've finished creating the component, you can move on to the next step.
  1. OnChanges
  2. DoCheck
  3. AfterContentChecked
  4. AfterViewChecked

Angular Lifecycle hook Example

Open the app.component.ts file and add the following code
import { ChangeDetectionStrategy, Component, VERSION } from "@angular/core";
 
@Component({
  selector: "my-app",
  changeDetection:ChangeDetectionStrategy.Default,
  template: `
    <h1>Angular Life Cycle Hooks</h1>
    Reference :
    <a
      href="https://www.tektutorialshub.com/angular/angular-component-life-cycle-hooks/#create-the-hook-method"
      >Angular Life Cycle Hooks</a
    >
 
    <h1>Root Component</h1>
 
 
    <br />
    <input
      type="text"
      name="message"
      [(ngModel)]="message"
      autocomplete="off"
    />
    <br />
    <input
      type="text"
      name="content"
      [(ngModel)]="content"
      autocomplete="off"
    />
 
 
    <br />
    hide child :
    <input
      type="checkbox"
      name="hideChild"
      [(ngModel)]="hideChild"
      autocomplete="off"
    />
 
    <br />
    <br />
    <app-child [message]="message" *ngIf="!hideChild">
      <!-- Injected Content -->
      <b> {{ content }} </b>
    </app-child>
 
    
  `
})
export class AppComponent {
  name = "Angular " + VERSION.major;
 
  message = "Hello";
  content = "Hello";
  hideChild=false;
 
  constructor() {
    console.log("AppComponent:Contructed");
  }
 
  ngOnChanges() {
    console.log("AppComponent:ngOnChanges");
  }
 
  ngOnInit() {
    console.log("AppComponent:ngOnInit");
  }
 
  ngDoCheck() {
    console.log("AppComponent:DoCheck");
  }
 
  ngAfterContentInit() {
    console.log("AppComponent:ngAfterContentInit");
  }
 
  ngAfterContentChecked() {
    console.log("AppComponent:AfterContentChecked");
  }
 
  ngAfterViewInit() {
    console.log("AppComponent:AfterViewInit");
  }
 
  ngAfterViewChecked() {
    console.log("AppComponent:AfterViewChecked");
  }
 
  ngOnDestroy() {
    console.log("AppComponent:ngOnDestroy");
  }
 
}
  • All hooks are being listened to and logged to the console.
  • Message and content are the two form fields. Both are passed to the child component. One is used as an input attribute, while the other is used to project content.
  • We can add or delete the ChildComponent from the DOM by using the hideChild form field. The ngIf directive is being used here.
  • Property binding is used to pass the message property to ChildComponent.
  • Projected content is passed as the content property.

Now, Open the child.component.ts file and add the following code
import { ChangeDetectionStrategy, Component, Input,  OnInit } from '@angular/core';
import { Customer } from './customer';
 
@Component({
  selector: 'app-child',
  changeDetection:ChangeDetectionStrategy.Default,
  template: `
  
      <h2>child component</h2>
 
      <br>
      <!-- Data as a input -->
      Message from Parent via @input {{message}}
      <br><br>
      <!-- Injected Content -->
      Message from Parent via content injection
      <ng-content></ng-content>
 
      <br><br><br>
      Code :
      <input type="text" name="code" [(ngModel)]="customer.code" autocomplete="off">
      <br><br>
      Name:
      <input type="text" name="name" [(ngModel)]="customer.name" autocomplete="off">
 
      <app-grand-child [customer]="customer"></app-grand-child>
  
  `
  
})
export class ChildComponent {
 
  @Input() message:string
 
  customer:Customer = new Customer()
 
 
constructor() {
    console.log("  ChildComponent:Contructed");
  }
 
  ngOnChanges() {
    console.log("  ChildComponent:ngOnChanges");
  }
 
  ngOnInit() {
    console.log("  ChildComponent:ngOnInit");
  }
 
  ngDoCheck() {
    console.log("  ChildComponent:DoCheck");
  }
 
  ngAfterContentInit() {
    console.log("  ChildComponent:ngAfterContentInit");
  }
 
  ngAfterContentChecked() {
    console.log("  ChildComponent:AfterContentChecked");
  }
 
  ngAfterViewInit() {
    console.log("  ChildComponent:AfterViewInit");
  }
 
  ngAfterViewChecked() {
    console.log("  ChildComponent:AfterViewChecked");
  }
 
  ngOnDestroy() {
    console.log("  ChildComponent:ngOnDestroy");
  }
 
}
  • All of the hooks are being listened to.
  • The @Input decorator transforms a message into an input property. It will get the information from the parent.
  • The placeholder for the projected content from the parent is ng-content>/ng-content>.
  • We pass the GrandChildComponent two form fields for the customer object.

Now, open the grandchild.component.ts  file and add the following code
import { ChangeDetectionStrategy, Component, Input,  OnInit } from '@angular/core';
import { Customer } from './customer';
 
@Component({
  selector: 'app-grand-child',
  changeDetection:ChangeDetectionStrategy.Default,
  template: `
  
      <h3>grand child component </h3>
 
      <br>
      Name {{customer.name}}
  
  `,
})
export class GrandChildComponent {
 
 
  @Input() customer:Customer
  
  constructor() {
    console.log("    GrandChildComponent:Contructed");
  }
 
  ngOnChanges() {
    console.log("    GrandChildComponent:ngOnChanges");
  }
 
  ngOnInit() {
    console.log("    GrandChildComponent:ngOnInit");
  }
 
 
  ngDoCheck() {
    console.log("    GrandChildComponent:DoCheck");
  }
 
  ngAfterContentInit() {
    console.log("    GrandChildComponent:ngAfterContentInit");
  }
 
  ngAfterContentChecked() {
    console.log("    GrandChildComponent:AfterContentChecked");
  }
 
  ngAfterViewInit() {
    console.log("    GrandChildComponent:AfterViewInit");
  }
 
  ngAfterViewChecked() {
    console.log("    GrandChildComponent:AfterViewChecked");
  }
 
  ngOnDestroy() {
    console.log("    GrandChildComponent:ngOnDestroy");
  }
}
  • All of the hooks are being listened to.
  • The client is marked as an input property via the @Input decorator. It will get the information from the parent.

Run the code and look for log messages in the console.

Conclusion

In Angular, we learned about component life cycle hooks. OnChanges, OnInit, DoCheck, AfterContentInit, AfterContentChecked, AfterViewInit, AfterViewChecked, and OnDestroy are the hooks generated by Angular. Then we learned how to use the OnInit life cycle hook to create an application. Finally, we looked at the order in which these life cycle hooks were executed.

I hope this article helps you and you will like it.👍

If you have any doubt or confusion then free to ask in the comment section.

Post a Comment

Previous Post Next Post