I have a problem by using a mask and a regex on an input.
This is the input:
<mat-form-field
>
<mat-label >HH:mm:ss:SSS</mat-label>
<input
matInput
[formControlName]="duration?.id"
[id]="duration?.id"
[name]="duration?.id"
placeholder="HH:mm:ss:SSS"
appDurationMask
type="text"
/>
<mat-error *ngIf="!isInvalidPattern"
>{{ duration?.label }} is required</mat-error
>
<mat-error *ngIf="isInvalidPattern"
>invalid pattern must be HH:mm:ss:SSS</mat-error
>
</mat-form-field>
The function isInvalidPattern looks like that:
get isInvalidPattern() {
return this.form.controls[this.data.id].errors
? this.form.controls[this.data.id].errors.pattern
: false;
}
The mask directive looks like that:
export class DurationMaskDirective {
constructor(public ngControl: NgControl) {}
@HostListener('ngModelChange', ['$event'])
onModelChange(event) {
this.onInputChange(event, false);
}
@HostListener('keydown.backspace', ['$event'])
keydownBackspace(event) {
this.onInputChange(event.target.value, true);
}
onInputChange(event, backspace) {
let newVal = event.replace(/\D/g, '');
if (backspace && newVal.length <= 6) {
newVal = newVal.substring(0, newVal.length - 1);
}
if (newVal.length === 0) {
newVal = '';
} else if (newVal.length <= 2) {
newVal = newVal.replace(/^(\d{0,2})/, '$1');
} else if (newVal.length <= 4) {
newVal = newVal.replace(/^(\d{0,2})(\d{0,2})/, '$1:$2');
} else if (newVal.length <= 6) {
newVal = newVal.replace(/^(\d{0,2})(\d{0,2})(\d{0,2})/, '$1:$2:$3');
} else if (newVal.length <= 9) {
newVal = newVal.replace(
/^(\d{0,2})(\d{0,2})(\d{0,2})(\d{0,3})/,
'$1:$2:$3:$4'
);
} else {
newVal = newVal.substring(0, 9);
newVal = newVal.replace(
/^(\d{0,2})(\d{0,2})(\d{0,2})(\d{0,3})/,
'$1:$2:$3:$4'
);
}
this.ngControl.valueAccessor.writeValue(newVal);
this.ngControl.valueAccessor.writeValue(newVal);
}
The problem is pretty simple, when i wrote something in the input that doesn't fit the pattern, even if nothing is visible, the invalidpattern is set to true.
If I wrote one number then delete it, the invalidpattern is set to true. If I wrote well my pattern then add 1 number or letter or anything, even if the only thing visible is the good pattern, invalidpattern is set to true. When I debug I see that even if I delete (by using backspace) it still keep in memory the last number even if nothing is visible for the user.
For example if in the input I wrote 1 then use backspace, the user see nothing in the input but the value of this.form.controls[this.metadata.id].value
is 1.
If I write 11:11:11:111 then add a 1 at the end, even if the input show 11:11:11:111 the value of this.form.controls[this.metadata.id].value
is 11:11:11:1111.
What can I do to resolve this problem?