Angular2 ngModelChange previous value
Asked Answered
L

6

39

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?

Lipski answered 21/10, 2016 at 8:56 Comment(0)
L
32

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);
Lipski answered 21/10, 2016 at 11:42 Comment(5)
This little caveat was costing me time, wasn't aware that the order of ngModel and ngModelChange made a difference.Valli
Oh, that is awkward! Why should the order make a difference?Hideandseek
one of the dumb things about Angular is that it seems these little nuances are more frequent than not. What a dumb feature, but thank you for finding this!Alger
Wow... Awesome find! This alongside Micronyks' answer would collectively be THE answer.Septivalent
Wow! This is weirdPrognostication
R
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 
}
Roscoeroscommon answered 21/10, 2016 at 9:1 Comment(4)
thank you, I marked your answer useful but it seems it won't show yet.Lipski
One tick mark is there. You just need to click it and it will apper in green color.Roscoeroscommon
@Irtaza click on 'grey check' on the left side of this answer (below points)Speciation
doesnt this breaks two way data binding?Decury
L
32

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);
Lipski answered 21/10, 2016 at 11:42 Comment(5)
This little caveat was costing me time, wasn't aware that the order of ngModel and ngModelChange made a difference.Valli
Oh, that is awkward! Why should the order make a difference?Hideandseek
one of the dumb things about Angular is that it seems these little nuances are more frequent than not. What a dumb feature, but thank you for finding this!Alger
Wow... Awesome find! This alongside Micronyks' answer would collectively be THE answer.Septivalent
Wow! This is weirdPrognostication
L
18

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

Lindon answered 15/3, 2018 at 14:25 Comment(3)
This is the correct answer. I did not know that the order of the (ngModelChange) and the [(ngModel)] inside the element is important. Thank youThereon
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!!Goodsized
If you need both on and new values then don't use the (ngModelChange)="eventHandlerMethod($event)", use the (change)="eventHandlerMethod($event)"Goodsized
G
4
<input (ngModelChange)="preTextChanged($event)" [(ngModel)]="text" (ngModelChange)="postTestChanged($event)">

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

Gan answered 22/5, 2019 at 15:4 Comment(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.Southeastwards
N
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/

Neologize answered 11/7, 2022 at 4:2 Comment(0)
B
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.

Brunildabruning answered 9/4, 2022 at 9:31 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.