ngOnChanges Lifecycle Hook

Understanding ngOnChanges

ngOnChanges is a lifecycle hook provided by Angular that is invoked whenever one or more input properties of a component change. This hook provides developers with a convenient way to detect changes in input properties and take appropriate actions in response to those changes.

Key Features of ngOnChanges:

  1. Invocation: ngOnChanges is invoked whenever input properties of a component change, including when the component is initially created.
  2. Input Changes Object: When ngOnChanges is invoked, it receives an object containing the previous and current values of all input properties that have changed.
  3. Simple Change Detection: ngOnChanges provides a straightforward mechanism for detecting changes in input properties without the need for complex manual tracking.

How to Use ngOnChanges:

Using ngOnChanges in Angular is straightforward. Developers simply need to implement the ngOnChanges method in their component class and define the desired behavior within this method. The ngOnChanges method receives a SimpleChanges object as an argument, which contains the previous and current values of all input properties that have changed. Developers can then access these values to perform any necessary actions, such as updating component state or triggering side effects.

How Does ngOnChanges Work?

When a component has input properties, Angular automatically detects changes to those properties and invokes the ngOnChanges method on the component whenever a change occurs. The ngOnChanges method receives a SimpleChanges object as an argument, which contains information about the previous and current values of the input properties that have changed.

When did ngOnChanges Called?

ngOnChanges lifecycle hook is called whenever the value of an input property on a component changes. This means that ngOnChanges is triggered whenever there is a change detected in the input properties passed to a component.

Here are some scenarios when ngOnChanges is called:

  1. Initial Component Render: When a component is initially rendered and input properties are passed to it, ngOnChanges is called to reflect the initial values of the input properties.
  2. Changes to Input Properties: Whenever there is a change in the value of an input property, Angular detects this change and triggers ngOnChanges to reflect the updated values.
  3. Asynchronous Data Binding: If input properties are bound to asynchronous data sources, such as observables or promises, ngOnChanges will be called when new data is emitted or resolved.
  4. Dynamic Input Property Changes: If input properties are dynamically changed within the component itself, ngOnChanges will be called to reflecct these changes.

Example:

import { Component, Input, OnChanges, SimpleChanges } from '@angular/core';

@Component({
  selector: 'app-example',
  templateUrl: './example.component.html',
  styleUrls: ['./example.component.css']
})
export class ExampleComponent implements OnChanges {
  @Input() data: any;

  ngOnChanges(changes: SimpleChanges) {
    // React to changes in input properties
    if (changes.data) {
      console.log('Previous value:', changes.data.previousValue);
      console.log('Current value:', changes.data.currentValue);
    }
  }
}

Example to Implement ngOnChanges

We will build an sample app that will demonstrate the use of ngOnChanges.

In this app we will have a app.component that would serve as a parent component and it will contain an input field and a submit button.

We will have another component named as  child-component that would just display the message in the paragraph tag with the use of string interpolation.

We will have a @Input property in the child component which will get its value from the parent component. In order to use this we need to import Input from @angular/core. Vs code does it automatically for us.

Next step is to use ngOnChanges hook function in child component. For this we need to implement OnChanges interface for the child component class.

export class ChildComponentComponent implements OnChanges {

}

Then define the ngOnChanges() hook function as shown below:

ngOnChanges() {
    console.log("ngOnChanges");
  }

Complete Code:

app.component.html

<div >
 <input type='text' #inputElm>
 <button (click)="onSubmit(inputElm)" >Submit</button>
 <app-child-component [message]="inputValue"></app-child-component>
</div>

app.component.css

.form{
    margin: 10px;
    padding: 10px;
    text-align: center;
}

app.component.ts

import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'my-angular-project';
  inputValue = "";

  constructor(){
    console.log("App Component Constructor Called.");
  }

  onSubmit(inputElm: HTMLInputElement){
    this.inputValue = inputElm.value;

  }
}

child-component.component.html

<p>Message: {{message}}</p>

child-component.component.ts

import { Component, Input, OnChanges } from '@angular/core';

@Component({
  selector: 'app-child-component',
  templateUrl: './child-component.component.html',
  styleUrls: ['./child-component.component.css']
})
export class ChildComponentComponent implements OnChanges {
  @Input() message: string = "";

  constructor() {
    console.log("Child Constructor called.");
  }

  ngOnChanges() {
    console.log("ngOnChanges");
  }

}

Output Observation

This is how out code outputs:

image-87.png

Console Output:

image-89.png

Notice in the above console log picture that the ngOnChanges gets called in the initial loading of the component. That is because ngOnChanges get called when the application loads the component first time.

Let's send some message through the input box field.

image-90.png

Noticed ngOnChanges called again when the input property get changed.

We can track the changes as well with SimpleChanges

Pass the parameter of type SimpleChanges to the ngOnChanges hook function as shown below:

ngOnChanges(changes: SimpleChanges) {
    console.log("ngOnChanges");
    console.log(changes);
  }

changes is an object that contains the following structure:

currentValue

firstChange
: 
boolean
previousValue

Let's see what this object contains when the ngOnChanges called first time while initialization of the component.

image-91.png

Here we can observe that, SimpleChange object has another object named as message (name from input property), it has currentValue set to “”, firstChange = true, and previousValue = undefined.

Let's Change the input with input box.

Noticed the current value has been changed.