Lifecycle Hooks
The Component Execution Lifecycle
In component-driven architectures, every component instance undergoes a structured, predictable operational lifecycle managed entirely by the framework engine. This lifecycle begins when the framework initializes the component class and renders its initial layout structure, tracks changes as data-bound properties update, and terminates when the instance is unmounted and stripped from the Active Document Object Model (DOM).
Lifecycle Hooks are specialized callback methods that allow developers to intercept this execution timeline. By declaring these specific methods inside a component, you can inject custom code loops to run automatically at critical operational milestones, such as configuring network calls, validating interface parameters, or cleaning up data streams.
The Phase Timeline Hierarchy
Lifecycle hooks execute in a strict, sequential chronological order, divided across three core operational phases: Initialization, Change Detection Sweeps, and Tear-down.
Phase 1: The Initialization Phase
1. ngOnChanges
Execution Milestone: Fires instantly after the component class constructor executes, and before the HTML template is initialized. It repeats continuously every single time an upstream parent component modifies a downstream
@Inputdata property reference.Primary Use Case: Intercepting external data updates. It receives a structured
SimpleChangesobject containing the previous property value, the current incoming property value, and a boolean flag indicating if this is the first execution loop.
2. ngOnInit
Execution Milestone: Triggers exactly once per component instantiation, immediately following the completion of the very first
ngOnChangessweep.Primary Use Case: The foundational landing zone for component initialization. This is where you configure external database calls, trigger backend REST API fetch requests, and initialize local form control values. Do not use the class constructor for network calls; use
ngOnInitto ensure input properties are fully mapped and available.
Phase 2: The Change Detection Sweep Phase
3. ngDoCheck
Execution Milestone: Runs immediately after every single change detection cycle execution loop, allowing you to catch and evaluate adjustments that the main compiling engine fails to detect automatically.
Primary Use Case: Implementing highly custom, fine-grained dirty checking logic, such as inspecting deep internal property mutations hidden within complex nested objects or arrays without altering object reference pointers.
4. ngAfterContentInit & ngAfterContentChecked
Execution Milestone:
AfterContentInitfires exactly once after the framework finishes projecting external HTML content inside the component's layout shell (using components like<ng-content>).AfterContentCheckedtriggers immediately after every subsequent checking cycle completes.Primary Use Case: Interfacing directly with child content blocks or reading layout metrics of elements marked via the
@ContentChildquery decorator.
5. ngAfterViewInit & ngAfterViewChecked
Execution Milestone:
AfterViewInitexecutes exactly once after the component's personal HTML template layout and all of its nested child component views are completely rendered onto the screen.AfterViewCheckedexecutes after every subsequent rendering verification sweep.Primary Use Case: Direct browser DOM manipulation. This is the earliest safe milestone where you can instantiate third-party charting libraries, query template HTML nodes via
@ViewChilddecorators, or measure exact canvas dimensions.
Phase 3: The Tear-down Phase
6. ngOnDestroy
Execution Milestone: Triggers exactly once immediately before the framework kills the component instance and purges its structural nodes completely out of the active DOM tree.
Primary Use Case: Memory leak prevention and resource cleanup. This is where you manually unsubscribe from active RxJS event streams, clear open browser execution intervals (
setInterval), disconnect from live WebSocket pipelines, and unbind custom raw document event listeners.
Implementation Syntax Blueprint
To compile an operational lifecycle hook, a TypeScript component class must explicitly import and declare the specific hook interface contract from the framework core library.
TypeScript
import {
Component,
OnInit,
OnChanges,
OnDestroy,
SimpleChanges,
Input
} from '@angular/core';
@Component({
selector: 'app-lifecycle-demo',
standalone: true,
template: `<p>Monitoring Active Job Profile: {{ jobId }}</p>`
})
export class LifecycleDemoComponent implements OnChanges, OnInit, OnDestroy {
@Input() jobId: number = 0;
constructor() {
console.log('1. Constructor: Class memory is allocated, but input properties are undefined.');
}
ngOnChanges(changes: SimpleChanges): void {
console.log('2. ngOnChanges: Intercepting data modifications.');
if (changes['jobId'] && !changes['jobId'].isFirstChange()) {
console.log(`Job ID altered from ${changes['jobId'].previousValue} to ${changes['jobId'].currentValue}`);
}
}
ngOnInit(): void {
console.log('3. ngOnInit: Component is initialized. Fetching job details from API server.');
// Primary location to trigger: this.jobService.fetchDetails(this.jobId);
}
ngOnDestroy(): void {
console.log('4. ngOnDestroy: Component is unmounting. Terminating open network sockets and subscriptions.');
}
}