Angular 4 Lifecycle Hooks

In this tutorial we will learn to use Lifecycle Hooks in Anuglar.

A component has a lifecycle managed by Angular.

Angular creates it, renders it, creates and renders its children, checks it when its data-bound properties change, and destroys it before removing it from the DOM.

Angular offers lifecycle hooks that provide visibility into these key life moments and the ability to act when they occur.

A directive has the same set of lifecycle hooks, minus the hooks that are specific to component content and views.

Lifecycle hooks are ngOnChanges, ngOnInit, ngDoCheck, ngAfterContentInit, ngAfterContentChecked, ngAfterViewInit, ngAfterViewChecked and ngOnDistroy.

Now we will explain every lifecycle hook one by one.

  1. ngOnChanges() – Respond when Angular (re)sets data-bound input properties. The method receives a SimpleChangesobject of current and previous property values. Called before ngOnInit() and whenever one or more data-bound input properties change.
  2. ngOnInit() – Initialize the directive/component after Angular first displays the data-bound properties and sets the directive/component’s input properties.  Called once, after the first ngOnChanges().
  3. ngDoCheck() – Detect and act upon changes that Angular can’t or won’t detect on its own. Called during every change detection run, immediately after ngOnChanges() and ngOnInit().
  4. ngAfterContentInit() – Respond after Angular projects external content into the component’s view. Called once after the first ngDoCheck().  A component-only hook.
  5. ngAfterContentChecked() – Respond after Angular checks the content projected into the component. Called after the ngAfterContentInit() and every subsequent ngDoCheck().  A component-only hook.
  6. ngAfterViewInit() – Respond after Angular initializes the component’s views and child views. Called once after the first ngAfterContentChecked() A component-only hook.
  7. ngAfterViewChecked() – Respond after Angular checks the component’s views and child views. Called after the ngAfterViewInit and every subsequent ngAfterContentChecked().A component-only hook.
  8. ngOnDestroy() – Cleanup just before Angular destroys the directive/component. Unsubscribe Observables and detach event handlers to avoid memory leaks. Called just before Angular destroys the directive/component.

And now we will make a simple project with all of these lifecycle hooks.

Create new project by runnig command ng new LifeCycleHooks and create child component of app component called child.component.

Put the following code inside app.component.ts

import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  showChild: boolean = true;
  title = 'app';

  onChange(value) {
    this.title = value;
  }

  toggleChild() {
    this.showChild = !this.showChild;
  }
}

and in app.component.html

<div style="text-align:center">
  
  <h1>
    Welcome to {{title}}!
  </h1>

  <img width="300" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNTAgMjUwIj4KICAgIDxwYXRoIGZpbGw9IiNERDAwMzEiIGQ9Ik0xMjUgMzBMMzEuOSA2My4ybDE0LjIgMTIzLjFMMTI1IDIzMGw3OC45LTQzLjcgMTQuMi0xMjMuMXoiIC8+CiAgICA8cGF0aCBmaWxsPSIjQzMwMDJGIiBkPSJNMTI1IDMwdjIyLjItLjFWMjMwbDc4LjktNDMuNyAxNC4yLTEyMy4xTDEyNSAzMHoiIC8+CiAgICA8cGF0aCAgZmlsbD0iI0ZGRkZGRiIgZD0iTTEyNSA1Mi4xTDY2LjggMTgyLjZoMjEuN2wxMS43LTI5LjJoNDkuNGwxMS43IDI5LjJIMTgzTDEyNSA1Mi4xem0xNyA4My4zaC0zNGwxNy00MC45IDE3IDQwLjl6IiAvPgogIDwvc3ZnPg==">

  <app-child *ngIf="showChild" [title]="title"></app-child>
</div>

<label for="title">Title:</label>
<input type="text" id="title" (change)="onChange(inputtitle.value)" #inputtitle [value]="title">

<button (click)="toggleChild()" >Toggle child component</button>

On button “Toggle child component” we add or remove our child component from the DOM ie. <app-child></app-child>.

In our added component child.component.ts add following code

import { Component, OnInit, OnChanges, DoCheck, AfterContentInit, AfterContentChecked, AfterViewInit, AfterViewChecked, OnDestroy, Input, SimpleChanges } from '@angular/core';
import { SimpleChange } from '@angular/core/src/change_detection/change_detection_util';

@Component({
  selector: 'app-child',
  templateUrl: './child.component.html',
  styleUrls: ['./child.component.css']
})
export class ChildComponent implements OnInit, OnChanges, DoCheck, AfterContentInit, AfterContentChecked, AfterViewInit, AfterViewChecked, OnDestroy {
  @Input('title') title;

  constructor() { }

  ngOnChanges(simpleChanges: SimpleChanges) {
    console.log("onChanges")
    console.log("onChanges previousValue", simpleChanges['title'].previousValue)
    console.log("onChanges currentValue", simpleChanges['title'].currentValue)
  }

  ngOnInit() {
    console.log("onInit")
  }

  ngDoCheck() {
    console.log("doCheck")
  }

  ngAfterContentInit() {
    console.log("afterContentInit")
  }

  ngAfterContentChecked() {
    console.log("afterContentChecked")
  }

  ngAfterViewInit() {
    console.log("afterViewInit")
  }

  ngAfterViewChecked() {
    console.log("afterViewChecked")
  }

  ngOnDestroy() {
    console.log("onDistroy")
  }

}

Our child component checks if the title property is changed.

And simply run application ng serve.

After running our app we can see in console in our browser in which order these hooks are showing up.

First comes onChanges with previous and current value, than onInit, doCheck, afterContentInit, afterContentChecked, afterViewInit, afterViewChecked, than doCheck again with afterContentChecked and afterViewChecked because doCheck is called during every change detection run.

Now if we change title in input, we can see that onChanges inside our child component is called and after that doCheck again with afterContentChecked and afterViewChecked because doCheck is called always after onChanges.

And if we remove child component from the DOM we can see that doCheck with afterContentChecked and afterViewChecked is called and onDestory at the end.

2017-12-30T20:26:04+01:00 26 decembar, 2017|Blog|0 Comments