Understanding ngOnChanges in Angular: Detecting Input Changes from Parent Components
Understanding ngOnChanges in Angular:
Detecting Input Changes from Parent Components
In Angular, the ngOnChanges lifecycle hook is a
powerful tool for tracking changes to @Input() properties passed from parent to
child components. It enables developers to react to data updates, reset
internal state, or trigger dependent logic in response to those changes.
What Is ngOnChanges?
The ngOnChanges() method is called whenever an
@Input() property changes. It receives a SimpleChanges object that contains the
previous and current values of all bound properties that have changed.
When to Use ngOnChanges
Here are 5 common use cases for ngOnChanges:
1. Reacting to Input Property Changes
When a child component receives new input and needs
to perform actions like fetching related data.
@Input() userId: number;
ngOnChanges(changes: SimpleChanges) {
if (changes['userId']) {
this.loadUserData(this.userId);
}
}
2. Resetting Component State
Reset internal fields, form states, or flags when
an input value updates.
@Input() resetFormTrigger: boolean;
ngOnChanges(changes: SimpleChanges) {
if (changes['resetFormTrigger']
&& this.resetFormTrigger) {
this.form.reset();
}
}
3. Comparing Previous and Current
Values
Useful for logging, audits, or conditional changes
based on value differences.
ngOnChanges(changes: SimpleChanges) {
const nameChange = changes['name'];
if (nameChange) {
console.log(`Name changed
from ${nameChange.previousValue} to ${nameChange.currentValue}`);
}
}
4. Conditional API Calls or DOM Updates
Trigger side effects such as API requests when
input changes.
@Input() productId: string;
ngOnChanges(changes: SimpleChanges) {
if (changes['productId'] &&
this.productId) {
this.fetchProductDetails(this.productId);
}
}
5. Cascading Dropdowns (Dependent
Inputs)
Update UI based on dependent values (like state
list based on country selection).
ts
CopyEdit
@Input() selectedCountry: string;
ngOnChanges(changes: SimpleChanges) {
if (changes['selectedCountry']) {
this.loadStatesForCountry(this.selectedCountry);
}
}
Full Example: Parent to Child with
ngOnChanges
1. Parent Component
// parent.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'app-parent',
template: `
<h2>Parent
Component</h2>
<input
[(ngModel)]="userName" placeholder="Enter name" />
<button (click)="changeUser()">Update
User</button>
<app-child
[name]="userName"></app-child>
`
})
export class ParentComponent {
userName: string = 'John';
changeUser() {
this.userName =
this.userName + '!';
}
}
2. Child Component
// child.component.ts
import { Component, Input, OnChanges, SimpleChanges
} from '@angular/core';
@Component({
selector: 'app-child',
template: `
<h3>Child
Component</h3>
<p>Current Name: {{
name }}</p>
<p
*ngIf="previousName">Previous Name: {{ previousName }}</p>
`
})
export class ChildComponent implements OnChanges {
@Input() name: string = '';
previousName: string | null = null;
ngOnChanges(changes: SimpleChanges):
void {
if (changes['name']) {
const change =
changes['name'];
this.previousName
= change.previousValue;
console.log(`Name
changed from ${change.previousValue} to ${change.currentValue}`);
}
}
}
3. App Module Setup
// app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from
'@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { AppComponent } from './app.component';
import { ParentComponent } from
'./parent.component';
import { ChildComponent } from './child.component';
@NgModule({
declarations: [AppComponent,
ParentComponent, ChildComponent],
imports: [BrowserModule, FormsModule],
bootstrap: [AppComponent]
})
export class AppModule {}
Using ngOnChanges with Nested Objects
Angular’s ngOnChanges only fires when object
references change. If you're passing a nested object, such as a user object,
you need to update it with a new reference.
Example
@Input() user: { name: string; age: number };
ngOnChanges(changes: SimpleChanges): void {
if (changes['user']) {
console.log('User
changed:', changes['user'].previousValue, '→', changes['user'].currentValue);
}
}
Tip: Use this.user = { ...this.user } in the parent
to trigger change detection.
Summary:
Use Case |
Description |
React to data changes |
Fetch data or run logic on input change |
Reset child state |
Clear forms or flags based on triggers |
Compare old vs new input values |
Useful for logs, validations, conditional updates |
Trigger chained UI/API logic |
E.g., update dropdowns, re-fetch on ID change |
Handle nested objects |
Requires reference change to detect updates |
Comments
Post a Comment