DEV Community

Cover image for ngOnChanges best practice - always use SimpleChanges - always

ngOnChanges best practice - always use SimpleChanges - always

Nick Raphael on November 05, 2019

ngOnChanges(): "A lifecycle hook that is called when any data-bound property of a directive changes. Define an ngOnChanges() method to handle the ...
Collapse
 
juanjoms profile image
Juan Miramontes

I have always used this approach to detect a specific change:

ngOnChanges(changes: SimpleChanges) {
  if (changes.myFirstInputParameter && changes.myFirstInputParameter.currentValue) {
    this.doSomething(this.myFirstInputParameter)
  }
}
Enter fullscreen mode Exit fullscreen mode

IMO it is simpler and more readable than the for/switch approach

Collapse
 
dennisf profile image
Dennis Frede • Edited

I currently go with the following. I think it's solid, and well readable:
defaultWidth and defaultHeight are some imported globally controlled variables.

  ngOnChanges(changes: SimpleChanges) {
    const {width, height, data} = changes;

    if (width) {
      const _width = width.currentValue ?? defaultWidth;
      // ...
    }

    if (height) {
      const _height = height.currentValue ?? defaultHeight;
      // ...
    }

    if (data) {
      const _data = data.currentValue ?? [];
      // ...
    }

  }
Enter fullscreen mode Exit fullscreen mode
Collapse
 
evolmk profile image
Miki (mike e) • Edited

need to add let change = changes[propName]; otherwise change.currentValue is undefined

ngOnChanges(changes: SimpleChanges) {
    for (const propName in changes) {
      if (changes.hasOwnProperty(propName)) {
        let change = changes[propName];
        switch (propName) {
          case 'pageSize': {
            console.log(`pageSize changed to:`, change.currentValue);
          }
        }
      }
    }
  }
Collapse
 
sebavicentea profile image
Seba Vicente

In this case, isn't it better to use a setter for each @Input instead of listen to ngOnChanges?

Collapse
 
nickraphael profile image
Nick Raphael

I think that comes down to personal preference. Personally, I find Input getters and setters to be too verbose. I like all inputs handled in the same place.

Collapse
 
hankchiutw profile image
Hank Chiu

I find Input getters and setters to be too verbose

checkout subjectize, which wraps the setter under the hood and you don't need a private variable.

Collapse
 
sproket profile image
sproket

WTF is 'change' in your example? I get cannot find name 'change'.

Collapse
 
mayanksamval profile image
mayanksamval

It's an oversight for sure! Use Changes[propName] instead

Collapse
 
kitkatsim profile image
Thiam Kiat Sim

this is a great way to illustrate how ngOnChanges works, thanks.
as pointed out by others, mistake in line:

this.doSomething(changes.myFirstInputParameter.currentValue)
Enter fullscreen mode Exit fullscreen mode
Collapse
 
miberg81_0 profile image
Michael Berger

I was practicing onChanges and ran into your post. Although I have only one input in my training app, I did fix it and added SimpleChanges to take care of the next developer, which happens to be me :)
I general life though from my observation there are few people who actually care about the next developer. Probably 2% from every 100 developers. It's sad, but everybody is obsessed to deliver smth. working, so people write some no so clean code. They get rewarded for such quick delivery, while nobody cares that the next developer will have a tough life...

Collapse
 
ajayer profile image
Ajay
great
Enter fullscreen mode Exit fullscreen mode
Collapse
 
ajayer profile image
Ajay
thanks
Enter fullscreen mode Exit fullscreen mode
Collapse
 
aydinmaz profile image
aydinmaz

Thanks man it was great ,I newly used ngOnChanges() , and by seeing your post I avoided future headaches !

Collapse
 
gadreash profile image
gadreash

Thanks Nick! Very helpful article.

Collapse
 
archieinet profile image
Archie

wt ?? it would be nice to put html in here..

Collapse
 
hbiori profile image
Hb Iori • Edited

I think that '' if (changes.hasOwnProperty(propName)) '' is useless
better to use '' if (changes[propName].currentValue) ''