Home  >  Angular 2

Angular 2/4 OnChanges + SimpleChanges Example

By Arvind Rai, July 27, 2017
On this page we will provide Angular OnChanges and SimpleChanges example. Angular provides lifecycle hooks for change detection. OnChanges is an interface and has a method declaration i.e 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 used in 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 value 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 then ngOnChanges() method will not run. In our Angular application OnChanges can be used for change detection of input properties. Now find the complete example step by step.

Technologies Used

Find the technologies being used in our example.
1. Angular 4.2.0
2. TypeScript 2.3.3
3. Node.js 6.10.1
4. Angular CLI 1.2.0
5. Angular Compiler CLI 4.2.0

Project Structure

Find the project structure of our demo application.
angular-demo
|
|--src
|   |
|   |--app 
|   |   |
|   |   |--employee.ts
|   |   |--employee.component.ts
|   |   |--employee.component.html
|   |   |--app.component.ts
|   |   |--app.component.html
|   |   |--app.module.ts
|   |   
|   |--main.ts
|   |--index.html
|   |--styles.css
|
|--node_modules
|--package.json

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: Employee;	
  @Input() message: 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);

        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: Employee;	
  @Input() message: string;	
  
  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;
} 

Run Demo Application

To run the demo application, find following steps.
1. Download source code using download link given below on this page.
2. Use downloaded src in your angular CLI application. To install angular CLI, find the link.
3. Run ng serve using command prompt.
4. Now access the URL http://localhost:4200
Angular 2/4 OnChanges + SimpleChanges Example

References

OnChanges
Lifecycle Hooks
SimpleChange

Download Source Code

POSTED BY
ARVIND RAI
ARVIND RAI
FIND MORE TUTORILAS





Copyright ©2017 concretepage.com, all rights reserved |Privacy Policy | Contact Us