Run Code When the Component Boots, Updates, Dies
Lifecycle Hooks
Angular calls well-defined hook methods at key points — initialisation, input changes, view ready, destruction.
What you'll learn
- Use ngOnInit for setup
- Use ngOnDestroy for cleanup
- Know when each hook fires
A component has a small set of named methods Angular will call automatically. Implement the ones you need.
The Common Hooks
import {
Component, OnInit, OnDestroy, OnChanges, AfterViewInit, SimpleChanges,
} from '@angular/core';
@Component({ selector: 'app-clock', standalone: true, template: '{{ now }}' })
export class ClockComponent implements OnInit, OnDestroy, OnChanges, AfterViewInit {
now = new Date();
private id?: number;
ngOnChanges(changes: SimpleChanges) {
// input bindings changed (legacy @Input only)
}
ngOnInit() {
// runs once, after first inputs are set — do setup here
this.id = window.setInterval(() => (this.now = new Date()), 1000);
}
ngAfterViewInit() {
// view children are rendered and queryable
}
ngOnDestroy() {
// clean up timers, subscriptions, listeners
clearInterval(this.id);
}
} Order of Calls
- constructor — DI happens
- ngOnChanges — when inputs arrive (legacy decorator inputs)
- ngOnInit — once, after first inputs
- ngAfterViewInit — once, after view is rendered
- ngOnDestroy — once, just before removal
The Modern Alternative
With signals, you usually do not need ngOnInit or ngOnChanges. An effect() declared in the constructor reacts to any signal read inside it — including signal inputs.
import { Component, DestroyRef, effect, inject, input } from '@angular/core';
@Component({ selector: 'app-greeter', standalone: true, template: '{{ name() }}' })
export class GreeterComponent {
name = input.required<string>();
private destroyRef = inject(DestroyRef);
constructor() {
effect(() => console.log('name changed:', this.name()));
this.destroyRef.onDestroy(() => console.log('bye'));
}
} DestroyRef.onDestroy() is the signal-era replacement for ngOnDestroy.