admin管理员组文章数量:1332395
I want to mask my input
value, basically I have an input field for credit card expiry date and want to mask it in format mm/yy
, this is what I had tried :
input-mask.directive.ts
import { Directive, HostListener } from '@angular/core';
import { NgControl } from '@angular/forms';
@Directive({
selector: '[formControlName][appInputMask]',
})
export class InputMaskDirective {
@HostListener('input', ['$event'])
onKeyDown(event: KeyboardEvent) {
const input = event.target as HTMLInputElement;
const trimmed = input.value.replace(/\s+/g, '').slice(0, 4);
if (trimmed.length > 3) {
return (input.value = `${trimmed.slice(0, 2)}/${trimmed.slice(2)}`);
}
}
}
I got my expected output, but the problem is when using backspace on input field, it messed up, here is my demo on stackblitz, how to solve this? or is there any better approach on input mask?
I want to mask my input
value, basically I have an input field for credit card expiry date and want to mask it in format mm/yy
, this is what I had tried :
input-mask.directive.ts
import { Directive, HostListener } from '@angular/core';
import { NgControl } from '@angular/forms';
@Directive({
selector: '[formControlName][appInputMask]',
})
export class InputMaskDirective {
@HostListener('input', ['$event'])
onKeyDown(event: KeyboardEvent) {
const input = event.target as HTMLInputElement;
const trimmed = input.value.replace(/\s+/g, '').slice(0, 4);
if (trimmed.length > 3) {
return (input.value = `${trimmed.slice(0, 2)}/${trimmed.slice(2)}`);
}
}
}
I got my expected output, but the problem is when using backspace on input field, it messed up, here is my demo on stackblitz, how to solve this? or is there any better approach on input mask?
Share Improve this question edited Oct 12, 2019 at 20:01 Sagar V 12.5k8 gold badges45 silver badges70 bronze badges asked Oct 12, 2019 at 11:43 hafizi hamidhafizi hamid 4112 gold badges22 silver badges44 bronze badges3 Answers
Reset to default 3The problems
HTMLInput element's maxlength should be 5 otherwise it won't allow a user to add 4 digits once you programmatically add a slash in it.
The same issue exist in
const trimmed = input.value.replace(/\s+/g, '').slice(0,4);
If it contains a slash, the slice should be end at 5 instead of 4.In
return
statementreturn (input.value = `${trimmed.slice(0, 2)}/${trimmed.slice(2)}`);
If the slash is added once, the ${trimmed.slice(2)
will return /\d{1,2}
. So you need to avoid the slash and start from 3.
The solution
change max length to 5 from 4
<input ... maxlength="5">
Now, input-mask.directive.ts need some changes
Change
const trimmed = input.value.replace(/\s+/g, '').slice(0,4);
to
const trimmed = input.value.replace(/\s+/g, '').slice(0, input.value.indexOf('/')==-1?4:5);
Because when you add /
, the length will bee 5.
Don't use
.slice(0)
because it allows a user to paste 5 digits and when you add a slash, it'll bee 6. So the date will look like11/111
instead of11/11
Change
return (input.value = `${trimmed.slice(0, 2)}/${trimmed.slice(2)}`);
to
return (input.value = `${trimmed.slice(0, 2)}/${trimmed.slice(trimmed.indexOf('/')==-1?2:3)}`);
This is where your code getting messed up. If it contains a slash, then you should slice it from 3. Else slice it from 2.
final code of HostListener in input-mask directive
@HostListener('input', ['$event'])
onKeyDown(event: KeyboardEvent) {
const input = event.target as HTMLInputElement;
const trimmed = input.value.replace(/\s+/g, '').slice(0, input.value.indexOf('/')==-1?4:5);
if (trimmed.length > 3) {
return (input.value = `${trimmed.slice(0, 2)}/${trimmed.slice(trimmed.indexOf('/')==-1?2:3)}`);
}
}
Working example : stackblitz
Use ngx-mask will make your work easy by just giving pattern for date, card, etc.
<input type='text' mask='99/99' >
Here is stackblitz demo
use below code . Create directive .ts file and add below code
import { Directive, HostListener } from '@angular/core';
import { NgControl } from '@angular/forms';
@Directive({
selector: '[formControlName][inputDateMask]',
})
export class InputMaskDirective {
constructor(public ngControl: NgControl) { }
@HostListener('ngModelChange', ['$event'])
onModelChange(event: any) {
this.onInputChange(event, false);
}
@HostListener('keydown.backspace', ['$event'])
keydownBackspace(event: any) {
this.onInputChange(event.target.value, true);
}
onInputChange(event: any, backspace: any) {
let newDate = '';
let month: string = "";
let day: string = "";
let year: string = "";
if (event)
newDate = event.replace(/\D/g, '');
if (backspace) {
newDate = newDate.substring(0, newDate.length - 1);
}
if (newDate.length > 7) {
if(newDate.match(/^[0-9]+$/) ? true : false)
month = newDate.substring(0, 2);
day = newDate.substring(2, 4);
year = newDate.substring(4, 8);
newDate = (`${month}/${day}/${year}`);
this.ngControl?.valueAccessor?.writeValue(newDate);
}
}
}
then declare directive in app.module.ts file
declarations: [
InputMaskDirective
],
exports: [
InputMaskDirective
]
use directive like this
<input matInput placeholder="MM/DD/YYYY" [maxlength]="10" inputDateMask formControlName="dateOfBirth" />
hope this help, thank you
本文标签: javascriptMask Input Value Date Format AngularStack Overflow
版权声明:本文标题:javascript - Mask Input Value Date Format Angular - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1742282667a2446380.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论