Skip to main content

Lifecyle hooks in Angular

Each Angular component goes through a lifecycle. This is managed by the Angular itself.

Angular creates a component, renders it, creates and renders its children, looks for the changes in its data-bound properties and destroys it.

Angular has lifecycle hooks for each such key moment and provide a way to act accordingly when such moment happens.

Directive and component have a lifecycle. For each lifecycle moment, Angular provides a lifecycle hook. The developer can hook into such moment by implementing the one or more specific lifecycle interfaces from the Angular core.

Angular provide following lifecycle hooks as under:

  1. ngOnChanges
  2. ngOnInit
  3. ngDoCheck
  4. ngAfterContentInit
  5. ngAfterContentChecked
  6. ngAfterContentInit
  7. ngAfterContentChecked
  8. ngOnDestroy
 

Sequence of execution of the lifecycle hooks

During the creation of component:

  • Constructor
  • ngOnChanges
  • ngOnInit
  • ngDoCheck
  • ngAfterContentInit
  • ngAfterContentChecked
  • ngAfterContentInit
  • ngAfterContentChecked

During change detection cycle:

  • ngOnChanges
  • ngDoCheck
  • ngAfterContentChecked
  • ngAfterContentChecked
 

Sequence of execution of lifecycle hooks with child

During creation of the component:

  • Parent Constructor
  • -->Child Constructor
  • Parent ngOnChanges
  • Parent ngOnInit
  • Parent ngDoCheck
  • Parent ngAfterContentInit
  • Parent ngAfterContentChecked
  • -->Child ngOnChanges
  • -->Child ngOnInit
  • -->Child ngDoCheck
  • -->Child ngAfterContentInit
  • -->Child ngAfterContentChecked
  • -->Child ngAfterViewInit
  • -->Child ngAfterViewChecked
  • Parent ngAfterViewInit
  • Parent ngAfterViewChecked

During change detection cycle:

  • Parent ngOnChanges
  • Parent ngDoCheck
  • Parent ngAfterContentChecked
  • -->Child ngOnChanges
  • -->Child ngDoCheck
  • -->Child ngAfterContentChecked
  • -->Child ngAfterViewChecked
  • Parent ngAfterViewChecked
The ngOnChanges hook is called during change detection cycle only when there is change in @Input bound property of the component.
 

Lifecycle hooks in Angular:

Constructor:

It executes very first when the component is created. It is called once. It is the best place to inject the dependency on which component depends upon.
@Component({
  ...
})
export class SomeComponent {
  private someservice: MyService;
  constructor(_service : MyService){ //1//
    this.someservice = _service;
  }
}
//1// SomeComponent has a dependency on MyService injected into the constructor of the component.

 

ngOnChanges:

It is called after the constructor and before the ngOnInit hook. It is called when there is a change in data-bound @input property of the component. It is called for child component when the parent component changes the value presented to the child component using @Input binding.
<child-component [childProperty] = 'parentProperty'></child-component>
ngOnChanges is called for ChildComponent when there is a change in parentProperty bound to the childProperty of the ChildComponent.

ngOnChanges hook receives a SimpleChanges object of current and previous values.

Let us elaborate it with an Example:

Let's consider that we have two component:

Parent Component: It has a property named 'mood' which present the current mood of the parent. It has two functions to make the parent's mood 'sad' and 'happy'. Initially, the parent is 'happy'.

Child Component: It also has a property named 'mood' which is bound to the current mood of the parent using @Input binding. It has a function to make itself 'sad'.

Let see the code first:
@Component({
   selector: 'parent-component',
   template: `
     <h3>The parent is {{mood}}</h3>
     <button (click)="makeParentSad()">Make Sad</button> //1//
     <button (click)="makeParentHappy()">Make Happy</button><br> //2//
     <child-component [mood] = 'mood' ></child-component> //3//
  `
 })
 export class ParentComponent {
   mood = "Happy";

   makeParentSad(){
     this.mood = "Sad";
   }

   makeParentHappy(){
     this.mood = "Happy";
   }
 }

 @Component({
   selector: 'child-component',
   template: `
     <h3>The child is {{mood}}</h3>
     <button (click)="makeChildSad()">Make Sad</button> //4//
   `
 })
 export class ChildComponent {
   @Input() mood;

   makeChildSad(){
    this.mood = 'Sad';
   }
   ngOnChanges(changes: SimpleChanges){
    console.log(`ngOnChange: ${JSON.stringify(changes)}`);
   }
 }
//1// and //2//: On clicking the buttons, the parent can changes its 'mood'. The ngOnChanges is only fired when the value of 'mood' is actually changed. If the parent is happy and clicking //2// button will not fire ngOnChanges.

//3//: The 'mood' of the parent is bounded with the 'mood' of the child component using @Input binding. When the 'mood' of the parent changes, the change will reflect in child component's 'mood'.

//4//: If we change the value of 'mood' internally firing makeChildSad() function, the ngOnChanges will not fire. This is because the parent's 'mood' hasn't changed and child's 'mood' is @Input bounded to the parent's 'mood'. In a simple word to fire ngOnChanges, there must be parent and child relationship and parent change the bound property of the child.

 

Let us change the above code as under:
class Book { //1//
   constructor(public subject:string, public cost:string) { }
}

@Component({
   selector: 'parent-component',
   template: `
     <h3>The parent book:</h3>
     <pre>{{book | json}}</pre>
     <input type="text" name="subject" [(ngModel)]="sub"/>
     <input type="text" name="cost" [(ngModel)]="cost"/>
     <button (click)="updateBook()">UpdateBook</button> //2//
     <child-component [book] = 'book'></child-component> //3//
   `
})
export class ParentComponent {
   book = new Book("Maths","100");
   sub:string = 'English';
   cost:string = '190';

   updateBook(){ //4//
     this.book.subject = this.sub;
     this.book.cost = this.cost;
   }
}

@Component({
   selector: 'child-component',
   template: `
     <h3>The child book:</h3>
    <pre>{{book | json}}</pre>
   `
})
export class ChildComponent {
   @Input() book;

   ngOnChanges(changes: SimpleChanges){
     console.log(`ngOnChange: ${JSON.stringify(changes)}`);
   }
}
//1//: We have defined a new class Book which has subject and cost property.

//2//: On clicking the UpdateBook button will update the book details.

//3//:book object is @Input bounded to the child component.

Now click the UpdateBook button. What happened? Is ngOnChanges fire? You would expect that it will fire but this is not true. updateBook() function reassign the subject and cost of the book. The ngOnChanges will not fire because Angular uses dirty checking (===) for the changes to fire ngOnChanges. On changing the property of the book object, the reference to the book doesn't change hence ngOnChanges not fired.

To make the ngOnChanges fires we have to update the updateBook() function as follows:
updateBook(){
   this.book = new Book(this.sub, this.cost);
}
In the updated version, we are creating a brand new book object passing the current subject and cost of the book. Now the ngOnChanges will fire.

Summary:

  • It is called after the constructor and before the ngOnInit hook.
  • It is called during change detection only when the @Input bound property is changed.
  • The ngOnChanges hook will for child component when the @Input bound property changes on parent component passed to the child component
  • The ngOnChanges hook will not fire when the @Input bound property changes internally.
  • The ngOnChanges hook will not fire when the @Input bound property is an object and we change the property of the bound object.

ngOnInit:

ngOnInit is called after ngOnChange and before ngDoCheck. It is called once during the lifecycle. This hook is used to initialize the component. At this time, all the data-bound properties are set. It can be used to load async data, subscribing to the observables etc.

ngDoCheck:

ngDoCheck is called after ngOnInit and before  the ngAfterContentInit hook. It fires for every change detection cycle. It is fire so frequently that it should have a very light code. It is used to detect the changes which ngOnChanges is not able to detect.

In ngOnChanges, we have seen that in two instances it never fires. This can be handled using ngDoCheck hooks.

Let's see the example code:

We have defined a CalcComponent which has three property namely cost, quantity and total. Cost and quantity can be changed by entering new values into the corresponding input box. The total must be in sync with the cost and quantity. Let's see the code below:
@Component({
  selector: 'calc-component',
  template: `
  Cost : <input name="cost" type="text" />
  Quantity : <input name="quantity" type="text" />
  Total : {{total}}
  `
})
export class CalcComponent {
  cost : number = 10;
  quantity : number = 20;
  total : number;
  constructor(){
    this.total = this.cost * this.quantity;
  }
  ngDoCheck(){
    console.log('ngDoCheck Called!!');
    if(this.total != this.cost * this.quantity){
      this.total = this.cost * this.quantity;
    }
  }
}
When ever the value of cost and quantity changes, the ngDoCheck will fire and it will update the correct value into the total. This can be done other ways.

ngAfterViewInit:

This will fire when the view child is initialize.

ngAfterViewChecked:

This will fire when the view child is checked.

ngAfterContentInit:

This will fire when the content child is initialize.

ngAfterContentChecked:

This will fire when the content child is checked.

Comments

  1. This comment has been removed by a blog administrator.

    ReplyDelete
  2. I gone through your blog, It was very much usefull for me,I gained so much of information through your blog ,This was very helfull and keep posting more,Thank you.

    Best Angularjs Training in Chennai

    Angular 6 Training in Chennai

    Angular 5 Training in Chennai

    ReplyDelete
  3. I believe there are many more pleasurable opportunities ahead for individuals that looked at your site. We are providing AngularJs training in Velachery.
    For more details: AngularJs training in Velachery

    ReplyDelete
  4. Needed to compose you a very little word to thank you yet again regarding the nice suggestions you’ve contributed here. Those guidelines additionally worked to become a good way to recognize that other people online have the identical fervor like mine to grasp great deal more around this condition. We are providing AngularJs training in velachery.
    For more details: AngularJs training in Velachery

    ReplyDelete
  5. Nice Post and informative data. Thank you so much for sharing this good post
    Angular JS Online training
    Angular JS training in Hyderabad

    ReplyDelete

Post a Comment

Popular posts from this blog

Automatic Slashing the Date Input using Angularjs

We define a directive that will automatically slash the input field as user typein the date. The directive have following capabiltiy: The directive will append slash '/' when input field has 2 or 5 characters. The input will accept only 10 characters (dd/mm/yyyy). Validity of date provide will not be checked. When the backspace is pressed it will remove the last two character if last character is slash. Otherwise it will remove last character from the input field. The input will not accept characters other than numbers (0 to 9). Let's jump into the code. We will use bootstrap for awesome look: HTML Code: <div class="container" ng-app="myApp" ng-controller="myAppCtrl"> <div class="row"> <div class="col-sm-8 col-sm-offset-2"> <form class="form-horizontal"> <h4 class="bg-primary">Auto Slashing Date using Angularjs Directive</h4> <div class=...

Code Syntax Highlighting on Blogger using Prismjs

Prismjs is developed by Lea Verou. It is a lightweight, extensible syntax highlighter, built with modern web standards in mind. It’s used in thousands of websites, including some of those you visit daily.Today, we will see how to use the prismjs on blogger to highlight our codes. It very easy and step by step process to follow: Goto to this link and get the personalized links for prismjs or simply copy the links given below: <link href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.6.0/themes/prism-coy.min.css" rel="stylesheet"></link> <script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.5.0/prism.min.js"></script> Goto Theme > Edit HTML and paste the links before the closing </head> section as shown below: Default prism.min.js file contain the functionality to highlight the code for only HTML, CSS and JS code. If you wish to use other language to highlight, you have to paste the link for that langu...

Conversion between Date String and Timestamp using Angularjs Directive

Let me ask you one question. Can a veiwValue and modelValue have same value into a different format? The answer is YES . Here we will see how it can be possible. We will see it through a simple example that converts date string (viewValue) into timestamp (modelValue). We will use a text box to enter a date string (dd/mm/yyyy) and convert it into timestamp that will be stored into model value. The trick is that we will use $parsers to convert the date string into the timestamp and $formatters to change the timestamp stored in modelValue to date string that will be shown on text input. Let's see the codes first: HTML Code: <h4>Date to Timestamp</h4> <div class="form-group"> <label for="date1" class="col-sm-3 control-label">Date1 VeiwValue:</label> <div class="col-sm-3"> <input type="text" id="date1" class="form-control" name="date1" ng-model="ob...