ngOnChanges Example | Angular

Last modified: June 6, 2019

ngOnChanges Example

ngOnInit Example

ngDoCheck Example

ngAfterContentInit Example

ngAfterContentChecked Example

ngAfterViewInit Example

ngAfterViewChecked Example

ngOnDestroy Example

child.component.ts

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

@Component({
  selector: 'app-child',
  template: `
    <a (click)="changeFromChild()">Change from child</a>
    <br/>
    {{parentData}}
  `
})
export class ChildComponent implements OnInit {
  @Input() parentData: any;
  constructor() {
  }

  ngOnInit() {
  }

  changeFromChild(){
    this.parentData -= 1;
  }

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

parent.component.ts

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

@Component({
  selector: 'app-parent',
  template: `
    <a (click)="changeFromParent()">Change from parent</a>
    <br/>
    <app-child [parentData]=data></app-child>
  `
})
export class ParentComponent implements OnInit {
  data = 0
  constructor() {
  }

  ngOnInit() {
  }

  changeFromParent(){
    this.data += 1;
  }
}

ngOnChanges() will fire before ngOnInit() and every time parentDatais updated from its parent component.

ngOnChanges() takes a changes argument of type SimpleChanges.

changeFromChild() won't call ngOnChanges()

changeFromParent() will call ngOnChanges()

When ngOnChanges() is called, this example simply logs the SimpleChanges instance.

The SimpleChanges instance looks like this...

class SimpleChange {
  constructor(previousValue: any, currentValue: any, firstChange: boolean)
  previousValue: any
  currentValue: any
  firstChange: boolean
  isFirstChange(): boolean
}

Every time ngOnChanges() is called, the SimpleChanges instance captures the parentData's:

  • previousValue
  • currentValue
  • firstChange (true the first time ngOnChanges is called)

Here is the SimpleChange object our example logs:

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


//console output
{
  parentData: { currentValue: 1, firstChange: false, previousValue: 0 }
}

What about multiple inputs?

Each bound variable is returned with its corresponding SimpleChanges instance in a single object.

//SimpleChanges object with multiple inputs
{
  parentData: { currentValue: 1, firstChange: false, previousValue: 0 },
  firstName: { currentValue: "Sam", firstChange: false, previousValue: "Eric" },
  age: { currentValue: 25, firstChange: false, previousValue: 20 }
}

ngOnChanges vs ngOnInit

ngOnInit gets called only once when the component is initialized.

ngOnChanges gets called before ngOnInit and whenever a component's bound input is changed FROM THE PARENT COMPONENT.

Remember that ngOnChanges is specific to bound inputs on the component. This means if you don't have any @Input properties on a child, ngOnChanges will never get called.

ngOnInit is specific to the component being initialized. ngOnChanges is specific to @Input properties on a child component.

When should you use ngOnChanges?

Use ngOnChanges whenever you want to detect changes from a variable decorated by @Input. Remember that only changes from the parent component will trigger this function.

Also remember that changes from the parent still update the child value even without implementing ngOnChanges. ngOnChanges simply adds the benefit of tracking those changes with previous and current value.

Responses:

Alexander Joseph
June 6, 2019
People often get confused when they see ngOnChanges fire before ngOnInit. At a high level you would assume ngOnInit is the first thing called when a component is rendered.

This post does a good job of emphasizing the fact that ngOnChanges is linked to children components and their bound @Input properties. When you initialize a child component from a parent, you are setting the component's @Input properties as part of the component's initialization....

A child component's @Input properties are updated even before the component is initialized...

You might also like: