How to use (change) and (ngModelChange) in Angular 9

0
3175
Angular 9

In this post we’re going to cover the difference between (change) and (ngModelChange) events with an input inside an Angular component.

First we need to understand that change is not an “Angular event”, it’s a DOM event.

Whereas ngModelChange is an Angular event. It fires when ngModel changes.

Essentially, we want to learn the difference between these and learn which one to use:

<input [value]="foo" (change)="changeFn($event)">
<input [ngModel]="bar" (ngModelChange)="modelChangeFn($event)">

The answer already lives above in our ngModel.

The (change) binding is listening for a DOM event called change, which will give us exactly what we’d expect in “plain JavaScript DOM” outside of the Angular system. Our changeFn($event) would then be given the regular Event object.

But (ngModelChange) is inside the Angular system, and we can further understand the difference between the two events by looking at the ngModel directive. The modelChangeFn($event) I’ve passed in will also give us something different to the previous changeFn($event) too, we’ll come onto this!

Before we do that, here’s how we’d typically use ngModel with its shorthand binding and event syntax (understanding this will make our lives easier):

<input [(ngModel)]="bar">

The above syntax is simply shorthand for an event callback and a model set all at once.

When the user wants to change the model, by entering text into the input, the event callback fires and sets the new value to the model.

So why (ngModelChange)? If we look at the ngModel directive source code we can see an @Output() (because it’s a directive it has an output). Here’s what the source reveals:

export class NgModel {
  //...
  @Output('ngModelChange') update = new EventEmitter();
  //...
}

The NgModel class has the update property with an EventEmitter instance bound to it. This means we can’t use (ngModelChange) without ngModel.

Whereas the (change) event can be used anywhere, and I’ve demonstrated that above with the [value] property binding instead.

It’s also worth noting that (ngModelChange) will only fire when the model is intended to be updated. Again here’s a piece from the ngModel source code:

export class NgModel {
  //...
  viewToModelUpdate(newValue: any): void {
    this.viewModel = newValue;
    this.update.emit(newValue);
  }
  //...
}

Something inside Angular will call viewToModelUpdate as we’re taking the model from our view (the input) and wanting to pass that update to the model, a well named method I’d say.

Really, if you’re using ngModel, you can just use the normal two-way binding syntax [(ngModel)] to sync both view and model at all times.

Comparing $event arguments

Let’s have a look at the differences that (change) and (ngModelChange) both give us. I’ve created this component to demonstrate the differences:

@Component({
  selector: 'my-app',
  template: `
  <div>
    <input [value]="foo" (change)="changeFn($event)">
    <p></p>
    <input [ngModel]="bar" (ngModelChange)="modelChangeFn($event)">
    <p></p>
  </div>
  `
})
export class AppComponent {
  foo = 'Hello';
  bar = 'World';
  changeFn(e) {
    this.foo = e.target.value;
  }
  modelChangeFn(value) {
    this.bar = value;
  }
}

There are a few things to note here:

  • Using (change) will only fire when the user has blurred the input
  • Using (ngModelChange) essentially is listening to the input event, and setting the model if a user types, pastes or changes the input’s value

And also:

  • With (change) we need to use the e.target.value as we’re given a plain DOM Event. From there, we can set the model value internally in the component!
  • With (ngModelChange) we are given the value as just e, which you could rename to value or something you prefer.

What about when the event fires and the model value is set?

  • The (change)=”changeFn($)” will fire after the value bound to [(ngModel)] has changed
  • The (ngModelChange)=”modelChangeFn($event)” will fire before the value bound to [(ngModel)] has changed.

Really, it comes down to using ngModel or not. If you’re using [(ngModel)] then you don’t need to worry about this, otherwise use (change) if you really want to provide some level of custom event or intercept the event before setting the model.

It’s always great to explore the source code, and I’d encourage you to check out the links above in your own time to learn a little more.

IF YOU ARE SERIOUS ABOUT YOUR ANGULAR SKILLS, YOUR NEXT STEP IS TO TAKE A LOOK AT MY ANGULAR COURSES WHERE YOU’LL LEARN ANGULAR, TYPESCRIPT, RXJS AND STATE MANAGEMENT PRINCIPLES FROM BEGINNING TO EXPERT LEVEL.

Now we fully understand the difference between (change) and (ngModelChange)! I hope you enjoyed the Article, thanks for reading!

Related: Run Angular in Docker

Angular LifeCycle