🅰️ Angular Q16 / 125

Explain the Angular component lifecycle hooks.

AI-Powered Answer ✓ Answered

Angular components and directives have a well-defined lifecycle, managed by Angular itself. Lifecycle hooks allow you to tap into key moments during a component's or directive's existence, from its creation to its destruction, enabling you to perform actions at specific times.

Understanding Lifecycle Hooks

Every Angular component has a lifecycle. Angular provides lifecycle hook interfaces that allow developers to hook into these lifecycle events, executing custom logic at precise moments. These hooks are methods prefixed with ng that are called by Angular automatically.

Primary Lifecycle Hooks

ngOnChanges

Responds when Angular sets or resets data-bound input properties. The method receives a SimpleChanges object of current and previous property values. This hook is called before ngOnInit and whenever one or more data-bound input properties change.

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

@Component({ selector: 'app-child', template: '<p>Value: {{ data }}</p>' })
export class ChildComponent implements OnChanges {
  @Input() data: string;

  ngOnChanges(changes: SimpleChanges): void {
    for (let propName in changes) {
      let change = changes[propName];
      let current = JSON.stringify(change.currentValue);
      let previous = JSON.stringify(change.previousValue);
      console.log(`${propName}: currentValue = ${current}, previousValue = ${previous}`);
    }
  }
}

ngOnInit

Initializes the component or directive after Angular first displays the data-bound properties and sets the component's input properties. This is a good place to fetch data from a server or perform other initialization tasks that don't depend on input changes.

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

@Component({ selector: 'app-hello', template: '<p>{{ message }}</p>' })
export class HelloComponent implements OnInit {
  message: string;

  ngOnInit(): void {
    this.message = 'Component initialized!';
    console.log('ngOnInit called');
  }
}

ngDoCheck

Detects and acts upon changes that Angular can't or won't detect on its own. It's called immediately after ngOnChanges and ngOnInit, and on every subsequent change detection run. Use with caution as it can impact performance.

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

@Component({ selector: 'app-docheck', template: '<p>DoCheck component</p>' })
export class DoCheckComponent implements DoCheck {
  ngDoCheck(): void {
    console.log('ngDoCheck called');
    // Implement custom change detection logic here
  }
}

ngAfterContentInit

Responds after Angular projects external content into the component's view. This hook is called once after the first ngDoCheck.

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

@Component({
  selector: 'app-parent-content',
  template: `
    <p>Parent Content</p>
    <ng-content></ng-content>
  `
})
export class ParentContentComponent implements AfterContentInit {
  @ContentChild('projectedContent') projectedContent: ElementRef;

  ngAfterContentInit(): void {
    console.log('ngAfterContentInit called. Projected content:', this.projectedContent?.nativeElement.textContent);
  }
}

ngAfterContentChecked

Responds after Angular checks the content projected into the component. Called after ngAfterContentInit and every subsequent ngDoCheck.

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

@Component({ selector: 'app-checked-content', template: '<ng-content></ng-content>' })
export class CheckedContentComponent implements AfterContentChecked {
  ngAfterContentChecked(): void {
    console.log('ngAfterContentChecked called');
  }
}

ngAfterViewInit

Responds after Angular initializes the component's views and child views. This hook is called once after the first ngAfterContentChecked.

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

@Component({
  selector: 'app-view-init',
  template: `
    <p #viewElement>This is part of the view.</p>
  `
})
export class ViewInitComponent implements AfterViewInit {
  @ViewChild('viewElement') viewElement: ElementRef;

  ngAfterViewInit(): void {
    console.log('ngAfterViewInit called. View element:', this.viewElement.nativeElement.textContent);
  }
}

ngAfterViewChecked

Responds after Angular checks the component's views and child views. Called after ngAfterViewInit and every subsequent ngAfterContentChecked.

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

@Component({ selector: 'app-view-checked', template: '<p>View Checked Component</p>' })
export class ViewCheckedComponent implements AfterViewChecked {
  ngAfterViewChecked(): void {
    console.log('ngAfterViewChecked called');
  }
}

ngOnDestroy

Cleans up just before Angular destroys the component or directive. This is the place to unsubscribe from observables, detach event handlers, and prevent memory leaks. It's called just before Angular destroys the directive/component.

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

@Component({ selector: 'app-destroy', template: '<p>Destroy Component</p>' })
export class DestroyComponent implements OnDestroy {
  private timerSubscription: Subscription;

  constructor() {
    this.timerSubscription = interval(1000).subscribe(num => console.log('Timer:', num));
  }

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

Order of Execution

The lifecycle hooks execute in a predictable sequence. For components, content hooks are called before view hooks, as content is projected before the component's own view is fully initialized. Changes to data-bound input properties trigger ngOnChanges.

  • ngOnChanges (when input properties change)
  • ngOnInit
  • ngDoCheck
  • ngAfterContentInit
  • ngAfterContentChecked
  • ngAfterViewInit
  • ngAfterViewChecked
  • ngOnDestroy (when component is destroyed)

Lifecycle Hooks Summary

HookPurposeWhen Called
ngOnChangesRespond when Angular sets/resets data-bound input properties.Before ngOnInit and on input changes.
ngOnInitInitialize the component/directive after Angular first displays data-bound properties.Once after ngOnChanges and component initialization.
ngDoCheckDetect and act upon changes not detected by Angular's default change detection.Immediately after ngOnChanges/ngOnInit and on every subsequent change detection run.
ngAfterContentInitRespond after Angular projects external content into the component's view.Once after the first ngDoCheck.
ngAfterContentCheckedRespond after Angular checks the content projected into the component.After ngAfterContentInit and every subsequent ngDoCheck.
ngAfterViewInitRespond after Angular initializes the component's views and child views.Once after the first ngAfterContentChecked.
ngAfterViewCheckedRespond after Angular checks the component's views and child views.After ngAfterViewInit and every subsequent ngAfterContentChecked.
ngOnDestroyClean up just before Angular destroys the component/directive.Just before Angular destroys the component/directive.