Change detection on primitive inputs in Angular 2
02 November 2016

Detecting input changes in Angular 2 are a bit tricky. The way Angular 2 detects changes and handles them can be rather confusing. Here’s how I do it.

What are inputs in Angular 2?

In Angular 2, parent components can pass data to child components through Inputs. On the parent's side, here's a sample:

1
<peg [pegColor]="peg1"></peg>

In the parent's html, the child component's selector and any inputs are added. Inputs are indicated by the square brackets.

On the child's side, it looks like this:

1
2
3
4
5
6
7
8
9
10
import { Component, Input } from '@angular/core';

@Component({
  selector: "peg",
  templateUrl: 'build/components/peg/peg.html'
})
export class PegComponent {
  @Input() pegColor: string;
  constructor() {}
}

Inputs are imported from core and declared using decorators (the @ symbol). Any data passed by the parent component to the child can then be accessed using this.user.

How does change detection work with Inputs?

Angular 2 tracks changes using dirty checking. This means Angular 2 determines that an Input has changed only if the input is primitive. So if it's a primitive value like a number, string, or boolean, as soon as the value changes, the child component knows about it. Moreover, for more complex inputs like arrays, if the reference to the array doesn't change, Angular 2 does not detect it. Changes will not be detected for array inputs if only one element in the array was changed.

How to use ngOnChanges for primitive inputs

Most likely, the reason you're reading this post is because you want to do something when the input changes. This can be done through Angular's ngOnChanges method. The documentation for it isn't as detailed as I would have hoped, but here's what I do.

1
2
3
4
5
6
7
8
9
10
export class PegComponent implements OnInit, OnChanges {
  @Input() pegColor: string;

  private coloredPeg: boolean;

  ngOnChanges(changes: SimpleChanges) {
    this.pegColorDisplay = changes['pegColor'].currentValue;
    this.coloredPeg = (this.pegColorDisplay !== null);
  }
}

The ngOnChanges method is passed a SimpleChanges object when called. changes['pegColor'].currentValue accesses the new value of the pegColor input.

And there you have it! I hope this helps!