Reputation: 1264
I'm having trouble updating an input while the user types.
I need to get a code from the user that looks like this: 354e-fab4 (2 alphanumeric groups of 4 chars separated by '-'). The user is not supposed to type the '-', it is inserted automatically. When the user types something that doesn't match the regexp used for validation, I want to revert back to the previous valid value.
The problem is that the value in the input is not updated properly when the validation fails. On the other hand, if I set a hard-coded string, the value is reflected in the input.
I isolated the problem in a stackblitz: https://stackblitz.com/edit/angular-qsbtiz
You may reproduce the issue by typing more than 8 characters: the regexp test fails, the code is set to the previous value, but the value is not reflected in the HTML input.
This is the method called for when the value of the input changes:
onCodeChange(newValue: string) {
const previousValue = this.code;
this.code = newValue;
const regex = new RegExp(/^([a-z0-9]{0,4})?(-)?([a-z0-9]{0,4})?(-)?$/);
// If the code doesn't match the regex, revert to the old value and return.
if (!regex.test(newValue)) {
// This changes this.code, but it's not reflected in the input's value.
this.code = previousValue;
// This changes this.code and it is reflected in the input's value.
//this.code = '1234';
} else {
const groups = regex.exec(newValue);
if (!groups[2] && groups[3]) {
this.code = `${groups[1]}-${groups[3]}`;
}
}
}
Please note that I'm interested in what's wrong with this code, not in an alternative solution like using a custom masked input component.
Thanks.
Upvotes: 3
Views: 828
Reputation: 2987
Since you spliting [(ngModel)]
. I would recommend to set it by passing the element it self to the onCodeChange()
function:
Stackbliz example
In template :
<input #input type="text" placeholder="" (ngModelChange)="onCodeChange($event,input)" [ngModel]="code"/>
In your TS file:
code = '';
previousValue = ''
onCodeChange(newValue: string, input) {
this.code = newValue;
const regex = new RegExp(/^([a-z0-9]{0,4})?(-)?([a-z0-9]{0,4})?(-)?$/);
if (!regex.test(newValue)) {
console.log("No match. Reverting the code to the previous value (this is not working as expected).");
input.value = this.previousValue;
} else {
const groups = regex.exec(newValue);
if (!groups[2] && groups[3]) {
this.code = `${groups[1]}-${groups[3]}`;
}
//Save previousValue here instead
this.previousValue = this.code
}
}
Upvotes: 3
Reputation: 251
If you want to restore the previous value then you should declare previousValue
and assign the value like this.
https://stackblitz.com/edit/angular-vdqbxz
And I changed the onModelchange
event to keyup
because the groups were not generating properly for some reason(IMO thats not related to this post).
Upvotes: 0