Physical Address

304 North Cardinal St.
Dorchester Center, MA 02124

Mastering Angular Lifecycle Hooks with Code Examples

Angular Lifecycle Hooks are essential for controlling the behavior of components in Angular applications.

Understanding how to use them can lead to cleaner, more efficient, and optimized code.

In this post, we’ll break down each of the major Angular Lifecycle Hooks with simple examples, so you can see how and when to use them.

What are Angular Lifecycle Hooks?

When an Angular component is created, it goes through several phases from birth to destruction.

Angular provides hooks that allow you to “tap” into these phases and execute code at specific times during the lifecycle of a component.

These hooks are methods you can implement in your component to run custom logic when certain events occur in the component’s lifecycle.

Key Angular Lifecycle Hooks

The most common lifecycle hooks you’ll encounter are:

  • ngOnChanges()
  • ngOnInit()
  • ngDoCheck()
  • ngAfterContentInit()
  • ngAfterContentChecked()
  • ngAfterViewInit()
  • ngAfterViewChecked()
  • ngOnDestroy()

Let’s explore each one in detail with examples.

1. ngOnChanges

The ngOnChanges() hook is invoked when any of the component’s input properties change. It’s useful when you want to react to changes in input data passed to the component.

import { Component, Input, OnChanges, SimpleChanges } from '@angular/core';

@Component({
  selector: 'app-hero',
  template: `
    <h3>{{heroName}}'s Power: {{power}}</h3>
  `
})
export class HeroComponent implements OnChanges {
  @Input() heroName: string;
  @Input() power: string;

  ngOnChanges(changes: SimpleChanges) {
    if (changes['heroName']) {
      console.log('Hero name changed:', changes['heroName'].currentValue);
    }
  }
}

Use Case: Imagine you are building a hero component where the name and power of the hero can change dynamically.

ngOnChanges() helps detect those changes and lets you perform any required actions.

2. ngOnInit

ngOnInit() is called once, right after the component is initialized. This is where you should place initialization logic that depends on the component’s input properties. Unlike ngOnChanges, ngOnInit is only called once during the component’s lifecycle.

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

@Component({
  selector: 'app-hero',
  template: `
    <h3>{{heroName}}'s Power: {{power}}</h3>
  `
})
export class HeroComponent implements OnInit {
  heroName: string = 'Spider-Man';
  power: string;

  ngOnInit() {
    this.power = 'Web-slinging';
    console.log('ngOnInit: Initializing hero component');
  }
}

Use Case: In this case, we initialize power to “Web-slinging” when the component is first created. ngOnInit() is perfect for fetching data from services or initializing variables after the component is set up.

3. ngDoCheck

ngDoCheck() is called every time change detection is triggered in the component. This hook allows you to implement custom change detection logic.

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

@Component({
  selector: 'app-hero',
  template: `
    <h3>{{heroName}}'s Power: {{power}}</h3>
  `
})
export class HeroComponent implements DoCheck {
  heroName: string = 'Batman';
  power: string = 'Detective Skills';

  ngDoCheck() {
    console.log('ngDoCheck: Custom change detection for hero component');
  }
}

Use Case: If Angular’s default change detection doesn’t fit your needs, you can override it with ngDoCheck() and implement custom logic to watch for specific changes.

4. ngAfterContentInit

ngAfterContentInit() is called once after Angular has projected content into the component. It’s useful for operations that need to interact with the projected content.

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

@Component({
  selector: 'app-hero',
  template: `
    <ng-content></ng-content>
  `
})
export class HeroComponent implements AfterContentInit {
  ngAfterContentInit() {
    console.log('ngAfterContentInit: Content has been projected into the hero component');
  }
}

Use Case: This hook is useful when you have content being passed into the component’s template using <ng-content>. After the content is projected, you can perform any initialization or updates based on that content.


5. ngAfterContentChecked

ngAfterContentChecked() is called after every check of projected content. If you need to perform some action whenever the content inside your component has been updated, use this hook.

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

@Component({
  selector: 'app-hero',
  template: `
    <ng-content></ng-content>
  `
})
export class HeroComponent implements AfterContentChecked {
  ngAfterContentChecked() {
    console.log('ngAfterContentChecked: Projected content has been checked');
  }
}

Use Case: Similar to ngAfterContentInit(), but this runs on every content check. This is helpful when you need to monitor dynamic content changes that might happen during the lifecycle of the component.

6. ngAfterViewInit

ngAfterViewInit() is called once after Angular initializes the component’s view and its child views. It’s the best place to manipulate the DOM elements of your component after they have been rendered.

import { Component, AfterViewInit, ViewChild, ElementRef } from '@angular/core';

@Component({
  selector: 'app-hero',
  template: `
    <h3 #title>{{heroName}}'s Power: {{power}}</h3>
  `
})
export class HeroComponent implements AfterViewInit {
  @ViewChild('title') title: ElementRef;

  ngAfterViewInit() {
    console.log('ngAfterViewInit: View initialized');
    this.title.nativeElement.style.color = 'blue';
  }
}

Use Case: Here, ngAfterViewInit() allows us to modify the DOM element directly after the view has been initialized. It’s often used for interacting with elements in the view, such as setting styles or triggering animations.

7. ngAfterViewChecked

ngAfterViewChecked() is called after every check of the component’s view. It’s useful when you need to perform operations after Angular has checked the view.

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

@Component({
  selector: 'app-hero',
  template: `
    <h3>{{heroName}}'s Power: {{power}}</h3>
  `
})
export class HeroComponent implements AfterViewChecked {
  ngAfterViewChecked() {
    console.log('ngAfterViewChecked: View has been checked');
  }
}

Use Case: Similar to ngAfterViewInit(), but this runs after every change detection check of the view. Use it for monitoring view changes, though avoid heavy logic here to prevent performance issues.

8. ngOnDestroy

ngOnDestroy() is called just before the component is destroyed. It’s an essential hook for cleaning up resources like event subscriptions, timers, or observables to prevent memory leaks.

import { Component, OnDestroy } from '@angular/core';
import { Subscription } from 'rxjs';

@Component({
  selector: 'app-hero',
  template: `
    <h3>{{heroName}}'s Power: {{power}}</h3>
  `
})
export class HeroComponent implements OnDestroy {
  private subscription: Subscription;

  ngOnDestroy() {
    console.log('ngOnDestroy: Cleaning up resources');
    if (this.subscription) {
      this.subscription.unsubscribe();
    }
  }
}

Use Case: ngOnDestroy() is crucial for preventing memory leaks. In this example, we unsubscribe from an observable when the component is destroyed to clean up resources.

Conclusion

Angular Lifecycle Hooks give developers fine control over the different stages of a component’s lifecycle.

Whether you’re dealing with initialization, change detection, or cleanup, there’s a hook for almost every situation.

By mastering these hooks, you can optimize performance, organize your code better, and build efficient Angular applications.

The most commonly used hooks are ngOnInit, ngOnChanges, and ngOnDestroy, but depending on your use case, others like ngAfterViewInit or ngDoCheck can be extremely valuable too!