Angular OnChanges + SimpleChanges Example

By Arvind Rai, February 13, 2024
On this page we will provide Angular OnChanges and SimpleChanges example. Angular provides lifecycle hooks for change detection. The OnChanges is an interface and has a method declaration as ngOnChanges() . In parent-child component, the child component declares @Input() property to get values from parent component. Whenever parent component changes the value of properties passed to child component decorated with @Input() then the method ngOnChanges() created in child component runs automatically. The method ngOnChanges() uses SimpleChanges as an argument that gives new and previous values of input values after changes. In case of input user object data type, ngOnChanges() is called only when the reference of object is changed in parent component. If we change only values of properties of an input user object, ngOnChanges() method will not run. In Angular application, OnChanges can be used for change detection of input properties.
Now find the complete example step-by-step.

SimpleChange Class and SimpleChanges Interface

SimpleChange class represents a basic change from a previous to new value. It has following class members. Suppose there is a change in input value, then following property can be used to detect changes.
previousValue: Keeps previous value of input property.
currentValue: Keeps current value of input property.
isFirstChange(): Boolean value that tells whether the new value is the first value assigned.

SimpleChanges is the interface that represents the changes object for all input property. SimpleChanges has the key as input property names and values are the instances of SimpleChange class.

OnChanges

OnChanges is a lifecycle hook that is called when any data-bound property of a directive changes. OnChanges is an interface that has a method declaration as follows.
ngOnChanges(changes: SimpleChanges) 
A component that needs to detect changes in its data-bound property of a directive, has to implement OnChanges interface and override its ngOnChanges() method. It has the argument as SimpleChanges that is used to get new and previous values of input property. They are used as follows.
import {Component, OnChanges, SimpleChanges, Input} from '@angular/core';

import { Employee } from './employee';
 
@Component({
  selector: 'app-emp',
  templateUrl: './employee.component.html'
})
export class EmployeeComponent implements OnChanges {
  @Input() employee = {} as Employee;	
  @Input() message = '';	

  ngOnChanges(changes: SimpleChanges) {
     for (let propName in changes) {  
	let change = changes[propName];
	let curVal  = JSON.stringify(change.currentValue);
	let prevVal = JSON.stringify(change.previousValue);

        console.log(curVal);
        console.log(prevVal);
     }
  }
} 

OnChanges with @Input() Primitive Type

Suppose we have following primitive type decorated with @Input() in a child component.
@Input() message: string; 
Now whenever parent component changes value in any of its property that has been used in child component, then in the child component the ngOnChanges() method runs. It works for any primitive data type such as string, number etc.

OnChanges with @Input() User Object Type

Suppose we have user object data type decorated with @Input() in child component.
@Input() employee: Employee; 
In child component when we have a user object as an @Input() data-bound property, then ngOnChanges() method is called only when the reference of the object is changed by parent component. Reference of the object can be changed by assigning new object to it. It means if we change value of property of object in parent component, then ngOnChanges() method will not be called in child component because reference is not changed.

Complete Example

employee.ts
export class Employee {
	constructor(public name: string, public age: number){}
} 
app.component.ts
import { Component } from '@angular/core';
import { NgForm } from '@angular/forms';

import { Employee } from './employee';
 
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html'
})
export class AppComponent {
  emp = new Employee('Mahesh', 20);	
  msg: string = 'Hello World!';

  onFormSubmit(empForm: NgForm) {
     let name = empForm.controls['name'].value;
     let age = empForm.controls['age'].value;
     this.emp = new Employee(name, age);
  }  
} 
app.component.html
<div class="employee">
  <form #empForm="ngForm" (ngSubmit)="onFormSubmit(empForm)">
    <p>Name: <input name="name" [ngModel]="emp.name"></p>
    <p>Age:<input name="age" [ngModel]="emp.age"></p>  
    <button>Submit</button>
  </form>
</div>	
<div class="message">
   <p>Message: <input [(ngModel)]="msg"/></p>
</div>	

<app-emp [employee]="emp" [message]="msg"></app-emp> 
employee.component.ts
import {Component, OnChanges, SimpleChanges, Input} from '@angular/core';

import { Employee } from './employee';
 
@Component({
  selector: 'app-emp',
  templateUrl: './employee.component.html'
})
export class EmployeeComponent implements OnChanges {
  @Input() employee = {} as Employee;	
  @Input() message = '';	
  
  allMsgChangeLogs: string[] = [];
  allEmployeeChangeLogs: string[] = [];
  
  ngOnChanges(changes: SimpleChanges) {
	  
	for (let propName in changes) {  
		let change = changes[propName];
		
		let curVal  = JSON.stringify(change.currentValue);
		let prevVal = JSON.stringify(change.previousValue);
		let changeLog = `${propName}: currentValue = ${curVal}, previousValue = ${prevVal}`;
		
		if (propName === 'message') {
		   this.allMsgChangeLogs.push(changeLog);
		} else if (propName === 'employee') {
		   this.allEmployeeChangeLogs.push(changeLog);
		}
        }
  }
} 
employee.component.html
<div>
  <b>Employee Change Log</b>
  <div *ngFor="let changeLog of allEmployeeChangeLogs">
     {{changeLog}}
  </div>
</div>
<br/><b>Message Change Log</b>
<div *ngFor="let changeLog of allMsgChangeLogs">
   {{changeLog}}
</div> 
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 { EmployeeComponent }  from './employee.component';

@NgModule({
  imports: [     
        BrowserModule,
	FormsModule
  ],
  declarations: [
        AppComponent,
	EmployeeComponent
  ],
  providers: [ 
  ],  
  bootstrap: [
        AppComponent
  ]
})
export class AppModule { } 
styles.css
.employee {
   background-color: #EEF4F5;	
   width: 350px;
}
.message {
   background-color: #EEF4F5;	
   width: 350px;
} 

Output

Find the print-screen of the output.
Angular OnChanges + SimpleChanges Example

References

OnChanges
Lifecycle hooks
SimpleChange

Download Source Code

POSTED BY
ARVIND RAI
ARVIND RAI







©2024 concretepage.com | Privacy Policy | Contact Us