Beginners Guide To Angular ngOnChanges (With Code Examples)

Luis Ramirez Jr
Luis Ramirez Jr
hero image

Are you curious about how ngOnChanges works and when to use it?

Well, then you've come to the right place!

In this comprehensive guide to Angular's ngOnChanges lifecycle hook, we'll explore how it works and why it's important, and I’ll explain how to use it effectively in your Angular applications.

I’ll even compare it against some other lifecycle hooks so that by the end of this guide, you'll feel far more confident in using ngOnChanges to make your components more robust and responsive.

So grab a coffee and a notepad and let's dive in!

Sidenote: If you want to dive deeper into Angular, as well as all of its lifecycle changes, and more, then check out my complete Angular Developer course.

learn angular this year

Fully updated and covering the latest Angular features for 2024, I guarantee that this is the most comprehensive online course on Angular.

You’ll also build confidence by creating real-world projects (including a massive video-sharing application similar to the example in this guide) step-by-step alongside me, Senior Developer!

With that out of the way, let’s get into the guide!

What is ngOnChanges in Angular, and how does it work?

ngOnChanges is one of the multiple lifecycle hooks available in Angular.

This particular hook gets called when any data-bound input property changes. It then notifies you when an input property changes and provides the current and previous values, allowing you to understand and react to these changes effectively.

For example

Suppose you have an interface component displaying a user's profile information.

initial profile

If the user updates their profile picture, Angular detects this change and triggers ngOnChanges.

update the profile image

(Fun fact - Netflix was built on Angular).

And so within the ngOnChanges function, you can write code to update the displayed picture, ensuring that the user sees their new profile image instantly.

This also makes it versatile for updating UI in sync with state and logging changes for debugging purposes!

So now we know what ngOnChanges is and how it works, let's look at how to use it.

How to use ngOnChanges

To use ngOnChanges, you just need to implement the OnChanges interface in your component and define the ngOnChanges method.

(This method takes one argument, such as an object adhering to the SimpleChanges interface, that contains the current and previous property values for each changed input property).

For example

Here's a basic implementation:

import { 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) {
    for (let propName in changes) {
      let change = changes[propName];
      let curVal = JSON.stringify(change.currentValue);
      let prevVal = JSON.stringify(change.previousValue);
      console.log(`${propName}: currentValue = ${curVal}, previousValue = ${prevVal}`);
    }
  }
}

What's happening here?

Well, in the ProfileComponent, we have a single @Input() property called name.

And so if the parent component changes the name, Angular calls the ngOnChanges method with a SimpleChanges object.

For example

If you were to change the name from 'John' to the name of our glorious leader 'Bruno', then the ngOnChanges method logs the following message:

name: currentValue = "Bruno", previousValue = "John"

Does ngOnChanges come before or after change detection?

It’s a little complicated in that ngOnChanges is called both before and after change detection, depending on the context.

Angular calls ngOnChanges at two specific points:

  1. When the component is initialized, before ngOnInit and after the first ngOnCheck
  2. Whenever one or more data-bound input properties change

For example

When a component is first being created, Angular goes through the following sequence of lifecycle hooks:

  1. Constructor: Angular invokes the component class constructor
  2. ngOnChanges: Angular calls this method whenever it detects changes to input properties. The first call happens before the component is fully initialized, which is before ngOnInit
  3. ngOnInit: It gets called once, after the first ngOnChanges. At this point, the component is fully initialized
  4. ngDoCheck: Angular calls this method immediately after ngOnInit and then every subsequent check of the component
  5. ngAfterContentInit and ngAfterContentChecked: These are called after Angular projects external content into the component's view
  6. ngAfterViewInit and ngAfterViewChecked: These are called when the component's view, and the views of its child directives, are fully initialized

This means that after the component is fully initialized and whenever Angular's change detection runs, it checks for changes in the values of properties and bindings. If it detects changes, it updates the view to match the current state of the component and then triggers ngOnChanges.

So like I said, in a way, ngOnChanges can come both before and after change detection.

Comparing ngOnChanges with other lifecycle hooks

We mentioned a few of the other lifecycle hooks above, so let’s look at a few and compare them to ngOnChanges.

ngOnInit vs ngOnChanges

  • Timing: ngOnChanges is called before ngOnInit during the component initialization phase. After that, ngOnChanges is called every time an input property changes, while ngOnInit is only called once.
  • Use Cases: ngOnInit is used for component initialization work, like calling a service to fetch data. ngOnChanges is used to perform actions in response to input property changes.

**For example:**sing ngOnInit for initialization

import { Component, OnInit } from '@angular/core';
import { DataService } from './data.service';

@Component({
  selector: 'app-data-fetcher',
  template: `<div>{{ data }}</div>`
})
export class DataFetcherComponent implements OnInit {
  data: string;

  constructor(private dataService: DataService) {}

  ngOnInit() {
    this.dataService.fetchData().subscribe(fetchedData => {
      this.data = fetchedData;
    });
  }
}

For example: Using ngOnChanges to react to input changes

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

@Component({
  selector: 'app-user-profile',
  template: `<h2>{{ user.name }}</h2>`
})
export class UserProfileComponent implements OnChanges {
  @Input() user: { name: string, age: number };

  ngOnChanges(changes: SimpleChanges) {
    if (changes['user']) {
      const currentValue = changes['user'].currentValue;
      const previousValue = changes['user'].previousValue;
      console.log('User changed from', previousValue, 'to', currentValue);
    }
  }
}

ngDoCheck vs ngOnChanges

  • ngOnChanges: Triggered when Angular detects changes to input properties and provides current and previous values for each changed property
  • ngDoCheck: Triggered every time Angular performs change detection, regardless of whether any changes were detected. Useful for tracking performance, debugging, or handling changes that Angular's default change detection may miss

For example: Using ngDoCheck for custom change detection

import { Component, DoCheck, Input, KeyValueDiffers, KeyValueDiffer } from '@angular/core';

@Component({
  selector: 'app-settings',
  template: `<div>Settings for {{ settings.theme }}</div>`
})
export class SettingsComponent implements DoCheck {
  @Input() settings: { theme: string, notifications: boolean };
  private differ: KeyValueDiffer<string, any>;

  constructor(private differs: KeyValueDiffers) {
    this.differ = this.differs.find({}).create();
  }

  ngDoCheck() {
    const changes = this.differ.diff(this.settings);
    if (changes) {
      changes.forEachChangedItem(item => {
        console.log('Changed item:', item.key, 'currentValue:', item.currentValue, 'previousValue:', item.previousValue);
      });
    }
  }
}

When to use ngOnChanges vs other lifecycle hooks

  • Use ngOnChanges to react to changes in input properties that may occur multiple times. If your component receives multiple input properties and requires complex calculations whenever any of these properties change, ngOnChanges is preferable
  • Use ngOnInit for initialization logic that relies on set input properties and needs to run once per component instantiation
  • Use ngDoCheck when you want to perform an action during every change detection cycle, regardless of whether any changes were detected

When to use alternatives vs ngOnChanges

As you can see, using ngOnChanges can be incredibly useful for detecting and reacting to changes in input properties.

However, for simpler or more performance-sensitive scenarios, then other Angular features might be more appropriate.

Example #1. When changes occur frequently

For properties that change very frequently (e.g., every few milliseconds), using ngOnChanges can lead to performance issues due to the high frequency of method calls.

Instead, consider using RxJS observables with the async pipe in your templates. This approach can be more efficient because Angular's change detection can be more finely controlled and optimized.

import { Component, Input, OnInit } from '@angular/core';
import { Observable, interval } from 'rxjs';
import { map } from 'rxjs/operators';

@Component({
  selector: 'app-stock-ticker',
  template: `<div>Current Price: {{ price$ | async }}</div>`
})
export class StockTickerComponent {
  @Input() stockSymbol: string;
  price$: Observable<number>;

  ngOnInit() {
    this.price$ = interval(1000).pipe(
      map(() => this.fetchStockPrice(this.stockSymbol))
    );
  }

  fetchStockPrice(symbol: string): number {
    // Simulate fetching stock price
    return Math.random() * 100 + 100;
  }
}

Example #2. When you need to react to changes in input properties to compute a value or trigger a side effect

For simple scenarios where you need to react to changes in input properties to compute a value or trigger a side effect, using a getter and setter for the input property might be sufficient and more straightforward than implementing ngOnChanges.

This approach allows you to handle changes immediately in the setter method.

private _inputValue: string;

@Input()
set inputValue(value: string) {
  this._inputValue = value;
  this.doSomething(value);
}

get inputValue(): string {
  return this._inputValue;
}

doSomething(value: string) {
  // React to the change
  console.log('Input value changed to', value);
}

Now it’s time to use this yourself

Hopefully this guide has opened up your eyes to some possibilities of how you might use this hook in your own projects.

Getting a handle on the ngOnChanges lifecycle hook in Angular is key for making your apps more dynamic and responsive.

  • It lets you react to changes in your component's input properties and ensures your UI stays up-to-date with the latest data
  • It’s also incredibly useful for fine-tuning how your app behaves when something changes, like updating a user profile or refreshing data
  • But remember, using it too much can slow things down, especially in bigger apps, so be considerate of how you use it

By getting comfortable with ngOnChanges and other Angular hooks, you'll be able to make your apps faster and more efficient!

P.S.

Remember, if you want to dive deeper into Angular and have a structured learning process that can take you from complete beginner to getting hired, then check out my complete Angular Developer course.

learn angular this year

Once you join, you’ll also have access to every other course in the Zero To Mastery library, as well as access to the private Discord.


You can ask questions from me, as well as chat with fellow students and working Angular Developers!

More from Zero To Mastery

Beginners Guide To Angular ngFor (With Code Examples) preview
Beginners Guide To Angular ngFor (With Code Examples)

Master the Angular ngFor directive and learn to manage dynamic lists, improve UI rendering, and optimize your Angular apps with this beginner's guide.

Top 5 In-Demand Tech Jobs For 2024 (+ How To Land A Job In Each!) preview
Top 5 In-Demand Tech Jobs For 2024 (+ How To Land A Job In Each!)

Want to get hired in a tech job in 2024? Pick one of these 5 if you want: 1) High salary 2) Jobs available now 3) Can learn the skills as a complete beginner.

How To Become A 10x Developer: Step-By-Step Guide preview
How To Become A 10x Developer: Step-By-Step Guide

10x developers make more money, get better jobs, and have more respect. But they aren't some mythical unicorn and it's not about cranking out 10x more code. This guide tells you what a 10x developer is and how anyone can become one.