37

Is there a way to get the previous(last) value of a field on ngModelChange? What I have goes something like this

HTML

<input type="text" [(ngModel)]="text" (ngModelChange)="textChanged($event)">

Handler

private textChanged(event) {
    console.log('changed', this.text, event);
}

What I get is

changed *newvalue* *newvalue*

Of course I can keep the older value using another variable, but is there a better way?

Rohan Fating
  • 2,135
  • 15
  • 24
irtaza
  • 721
  • 1
  • 6
  • 13

6 Answers6

44

What you can do is,

DEMO : http://plnkr.co/edit/RXJ4D0YJrgebzYcEiaSR?p=preview

<input type="text" 
       [ngModel]="text"                      //<<<###changed [(ngModel)]="text" to [ngModel]="text"
       (ngModelChange)="textChanged($event)"> 

private textChanged(event) {        
    console.log('changed', this.text, event);
    this.text=event;                          //<<<###added 
}
micronyks
  • 54,797
  • 15
  • 112
  • 146
31

So found kinda weird(at least for me) possible solution for this with least changes in the code in question. So on assigning the (ngModelChange) attribute before [(ngModel)] what I get is following with the same handler:

changed *older value* *new value*

I get the new value in this.textlike so:

setTimeout(() => console.log(this.text), 0);
irtaza
  • 721
  • 1
  • 6
  • 13
15

all you need to do is to put (ngModelChange)="textChanged($event)" to the left of [(ngModel)] element in the html tag, like:

<input (whatever...) (ngModelChange)="textChanged($event)" [(ngModel)]="text">

This way, inside textChanged(event), the element you are binding to still has the previous value, while event is the new one

If you type

<input (whatever...) [(ngModel)]="text" (ngModelChange)="textChanged($event)">

The event will be called with new value only. However:

<input (whatever...) (ngModelChange)="textChanged($event)" [(ngModel)]="text" (ngModelChange)="textChanged($event)">   - 

Will get you both events with previous and current value

DiSaSteR
  • 608
  • 6
  • 11
  • 2
    This is the correct answer. I did not know that the order of the (ngModelChange) and the [(ngModel)] inside the element is important. Thank you – Developer Thing Feb 28 '19 at 15:52
  • Yes this is the correct workaround for the Angular bug!! In the Angular Doco, under ngModel it says: "Event emitter for producing the ngModelChange event after the view model updates." NOTE the "after the view model updates" So that would make it a Angular bug, because it is NOT deterministic!! – GregJF Jul 15 '20 at 01:59
  • If you need both on and new values then don't use the (ngModelChange)="eventHandlerMethod($event)", use the (change)="eventHandlerMethod($event)" – GregJF Jul 15 '20 at 02:05
2
<input (ngModelChange)="preTextChanged($event)" [(ngModel)]="text" (ngModelChange)="postTestChanged($event)">

In this way you can know the previous value and the next value

Dani Andújar
  • 1,116
  • 1
  • 12
  • 15
  • 1
    This behavior was so strange to me. Why would the attribute position for a tag make any difference? They should be named separate. Thank you for clearing this for me. – Jimmy Garpehäll Feb 17 '20 at 13:32
1

You can use getters and setters to retain older values. E.g.

HTML

<input type="text" [(ngModel)]="text" (ngModelChange)="textChanged($event)">

TypeScript:

private _text: string = "";
private _oldText: string = "";
get text(): string{
    return this._text;
}
set text(value: string) {
    this._oldText = this._text;
    this._text = value;
}

Source: https://www.typescripttutorial.net/typescript-tutorial/typescript-getters-setters/

OliviaLynn
  • 123
  • 7
0

This worked for me.

<input
   [(ngModel)]="actionInputValue"
   (keydown)="prevValue = actionInputValue"
   (keyup)="doSomething()"
/>

Now in component ts file you can console and check the values.

doSomething() {
  console.log(this.prevValue, this.actionInputValue);
}

The idea is that keydown event occurs before the ngModel is updated.

Animesh Rawat
  • 197
  • 3
  • 9