Skip to content
intermediate Phase 3 · Components, Templates, and Lifecycle

Component Lifecycle Hooks

Hook into initialization, change detection, and teardown stages.

45m
0 problems
Topic Progress 0%

The Lifecycle Sequence

Angular calls lifecycle hooks in a specific order as a component is created, updated, and destroyed. Understanding this sequence helps you place logic in the right hook.

Lifecycle Order

1. constructor()          — Dependency injection, initial field setup
2. ngOnChanges()          — Called when @Input values change (before ngOnInit)
3. ngOnInit()             — Called once after the first ngOnChanges
4. ngDoCheck()            — Called during every change detection cycle
5. ngAfterContentInit()   — Called once after content (ng-content) is projected
6. ngAfterContentChecked()— Called after every check of projected content
7. ngAfterViewInit()      — Called once after the component's view is rendered
8. ngAfterViewChecked()   — Called after every check of the component's view
9. ngOnDestroy()          — Called once before the component is destroyed

ngOnInit — The Standard Initialization Hook

Use ngOnInit for logic that runs once after inputs are first set:

@Component({
  selector: 'app-user-list',
  template: `<p *ngFor="let user of users">{{ user.name }}</p>`,
})
export class UserListComponent implements OnInit {
  @Input() userId!: number;
  users: User[] = [];

  constructor(private userService: UserService) {}

  ngOnInit(): void {
    this.userService.getUsers(this.userId).subscribe(users => {
      this.users = users;
    });
  }
}

ngOnChanges — Reacting to Input Changes

@Component({
  selector: 'app-counter',
  template: `<p>Count: {{ count }}</p>`,
})
export class CounterComponent implements OnChanges {
  @Input() count!: number;

  ngOnChanges(changes: SimpleChanges): void {
    if (changes['count']) {
      console.log('Previous:', changes['count'].previousValue);
      console.log('Current:', changes['count'].currentValue);
      console.log('First change:', changes['count'].firstChange);
    }
  }
}

ngOnDestroy — Cleanup

Always clean up subscriptions, timers, and event listeners in ngOnDestroy:

@Component({
  selector: 'app-timer',
  template: `<p>Elapsed: {{ seconds }}s</p>`,
})
export class TimerComponent implements OnInit, OnDestroy {
  seconds = 0;
  private intervalId: any;
  private subscription: Subscription = new Subscription();

  ngOnInit(): void {
    this.intervalId = setInterval(() => this.seconds++, 1000);

    this.subscription.add(
      this.someService.data$.subscribe(data => {
        // handle data
      })
    );
  }

  ngOnDestroy(): void {
    clearInterval(this.intervalId);
    this.subscription.unsubscribe();
  }
}

Advanced Hooks: DoCheck, AfterView, AfterContent

Beyond the basic hooks, Angular provides additional hooks for specialized scenarios.

ngDoCheck — Custom Change Detection

Called during every change detection cycle. Use it to implement custom change detection logic:

@Component({
  selector: 'app-todo-list',
  template: `<p *ngFor="let todo of todos">{{ todo.text }}</p>`,
})
export class TodoListComponent implements DoCheck {
  @Input() todos: Todo[] = [];
  private previousCount = 0;

  ngDoCheck(): void {
    if (this.todos.length !== this.previousCount) {
      console.log('Todo count changed:', this.previousCount, '->', this.todos.length);
      this.previousCount = this.todos.length;
    }
  }
}

ngAfterViewInit — Accessing the DOM

Called after the component's view is fully rendered. Use it to interact with DOM elements:

@Component({
  selector: 'app-chart',
  template: `<canvas #chartCanvas></canvas>`,
})
export class ChartComponent implements AfterViewInit {
  @ViewChild('chartCanvas') canvasRef!: ElementRef<HTMLCanvasElement>;

  ngAfterViewInit(): void {
    const ctx = this.canvasRef.nativeElement.getContext('2d');
    // Initialize chart library
  }
}

ngAfterContentInit — Projected Content

Called after ng-content is projected into the component:

@Component({
  selector: 'app-card',
  template: `<div class="card"><ng-content></ng-content></div>`,
})
export class CardComponent implements AfterContentInit {
  @ContentChild('header') headerRef!: ElementRef;

  ngAfterContentInit(): void {
    console.log('Projected header:', this.headerRef?.nativeElement.textContent);
  }
}

Lifecycle Hook Interfaces

Each hook has a corresponding interface for type safety:

Hook Interface
ngOnInit OnInit
ngOnChanges OnChanges
ngDoCheck DoCheck
ngAfterContentInit AfterContentInit
ngAfterContentChecked AfterContentChecked
ngAfterViewInit AfterViewInit
ngAfterViewChecked AfterViewChecked
ngOnDestroy OnDestroy
export class MyComponent implements OnInit, OnDestroy {
  ngOnInit(): void {}
  ngOnDestroy(): void {}
}

Quiz

1. Which lifecycle hook is called once after the component's inputs are first set?

Question 1 options

2. Where should you clean up subscriptions and timers?

Question 2 options

3. What is the correct order of the first three lifecycle hooks?

Question 3 options

Flashcards

Question

What is the lifecycle hook order?

Answer

constructor -> ngOnChanges -> ngOnInit -> ngDoCheck -> ngAfterContentInit -> ngAfterContentChecked -> ngAfterViewInit -> ngAfterViewChecked -> ngOnDestroy

Question

When do you use ngOnInit?

Answer

For one-time initialization logic that depends on @Input values being set. Called once after the first ngOnChanges.

Question

Where do you clean up subscriptions?

Answer

ngOnDestroy — unsubscribe from Observables, clear intervals/timeouts, remove event listeners.

Revision Notes

Key Takeaways

  • 1. ngOnInit is the standard initialization hook
  • 2. ngOnDestroy is mandatory for cleanup to prevent memory leaks
  • 3. ngOnChanges fires before ngOnInit and on every input change
  • 4. AfterViewInit is the safe place to access DOM elements

Interview Tips

  • • Be able to recite the lifecycle order
  • • Explain why cleanup in ngOnDestroy prevents memory leaks
  • • Mention that ngDoCheck runs on every change detection cycle

Cheat Sheet

Lifecycle Hooks Cheat Sheet

Order:

constructor -> ngOnChanges -> ngOnInit -> ngDoCheck
-> ngAfterContentInit -> ngAfterContentChecked
-> ngAfterViewInit -> ngAfterViewChecked -> ngOnDestroy

Common uses:

  • ngOnInit: fetch data, setup subscriptions
  • ngOnChanges: react to input changes
  • ngOnDestroy: cleanup subscriptions and timers
  • ngAfterViewInit: DOM manipulation
  • ngDoCheck: custom change detection

Interfaces:

implements OnInit, OnChanges, OnDestroy

Continue Learning