如何为Angular Material 14日期范围选择器添加输入掩码
Angular Material 14日期范围选择器实现手动输入自动掩码(dd/mm/YYYY)
解决方案:自定义输入掩码指令
Angular Material 14本身没有内置日期输入掩码功能,最可靠的方式是编写自定义指令处理输入格式化,同时限制仅允许数字输入。
步骤1:创建日期掩码指令
新建date-mask.directive.ts文件,实现输入时自动插入/分隔符并过滤非数字字符:
import { Directive, HostListener, ElementRef } from '@angular/core'; @Directive({ selector: '[appDateMask]' }) export class DateMaskDirective { constructor(private el: ElementRef) {} // 实时监听输入并格式化 @HostListener('input', ['$event']) onInput(event: KeyboardEvent) { const input = this.el.nativeElement; // 移除所有非数字字符 let cleanValue = input.value.replace(/\D/g, ''); let formattedValue = ''; // 按dd/mm/yyyy规则拼接内容 if (cleanValue.length > 0) { formattedValue += cleanValue.substring(0, 2); if (cleanValue.length > 2) { formattedValue += '/' + cleanValue.substring(2, 4); if (cleanValue.length > 4) { formattedValue += '/' + cleanValue.substring(4, 8); // 限制年份最多4位 } } } input.value = formattedValue; event.preventDefault(); } // 失去焦点时补充分隔符或修正格式 @HostListener('blur') onBlur() { const input = this.el.nativeElement; const cleanValue = input.value.replace(/\D/g, ''); switch (cleanValue.length) { case 2: input.value = `${cleanValue}/`; break; case 4: input.value = `${cleanValue.substring(0,2)}/${cleanValue.substring(2,4)}/`; break; case 6: case 7: case 8: input.value = `${cleanValue.substring(0,2)}/${cleanValue.substring(2,4)}/${cleanValue.substring(4,8)}`; break; default: // 输入长度不足时可选择清空或保留现有内容 break; } } }
步骤2:在模块中注册指令
在根模块(如AppModule)中声明并导出该指令:
import { DateMaskDirective } from './date-mask.directive'; @NgModule({ declarations: [ // ...其他组件/指令 DateMaskDirective ], exports: [ // 若需在其他模块使用,导出指令 DateMaskDirective ] }) export class AppModule { }
步骤3:在模板中应用指令
给日期范围选择器的输入框添加appDateMask指令:
<mat-form-field appearance="fill"> <mat-date-range-input [rangePicker]="picker" [max]="today"> <input matStartDate [(ngModel)]="item.startValue" [placeholder]="'Of' | translate" #dateRangeStart appDateMask (keypress)="validation($event, index)"> <input matEndDate [(ngModel)]="item.endValue" [placeholder]="'Till' | translate" #dateRangeEnd appDateMask (dateChange)="dateRangeChange(index)" (keypress)="validation($event, index)"> </mat-date-range-input> <mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle> <mat-date-range-picker #picker (closed)="afterClose(item, index)"></mat-date-range-picker> </mat-form-field>
优化输入验证逻辑
修改原validation方法,仅允许数字输入,并增加日期合法性校验:
validation(event: KeyboardEvent, index: number) { // 仅允许数字和退格键输入 const charCode = event.which || event.keyCode; if (charCode !== 8 && (charCode < 48 || charCode > 57)) { event.preventDefault(); return false; } if (this.filterList[index].validation) { if (this.filterList[index].type === 'date') { // 校验日期格式合法性(dd/mm/yyyy) const dateStr = this.filterList[index].startValue; const dateParts = dateStr.split('/'); if (dateParts.length === 3) { const day = parseInt(dateParts[0], 10); const month = parseInt(dateParts[1], 10); const year = parseInt(dateParts[2], 10); // 验证日期是否有效 const validDate = new Date(year, month - 1, day); if (validDate.getDate() !== day || validDate.getMonth() + 1 !== month || validDate.getFullYear() !== year) { return { date: true }; } } } // 保留原有validation逻辑 if (eval(this.filterList[index].validation)) { return true; } return false; } }
统一日期格式(选择器与手动输入)
日期选择器返回的是Date对象,手动输入的是字符串,需统一格式。在dateChange和afterClose方法中转换:
dateRangeChange(index: number) { // 将选择器返回的Date对象转为dd/mm/yyyy字符串 if (this.item.endValue instanceof Date) { const day = this.item.endValue.getDate().toString().padStart(2, '0'); const month = (this.item.endValue.getMonth() + 1).toString().padStart(2, '0'); const year = this.item.endValue.getFullYear(); this.item.endValue = `${day}/${month}/${year}`; } // 原有的业务逻辑 } afterClose(item: any, index: number) { // 处理起始日期 if (item.startValue instanceof Date) { const day = item.startValue.getDate().toString().padStart(2, '0'); const month = (item.startValue.getMonth() + 1).toString().padStart(2, '0'); const year = item.startValue.getFullYear(); item.startValue = `${day}/${month}/${year}`; } // 处理结束日期 if (item.endValue instanceof Date) { const day = item.endValue.getDate().toString().padStart(2, '0'); const month = (item.endValue.getMonth() + 1).toString().padStart(2, '0'); const year = item.endValue.getFullYear(); item.endValue = `${day}/${month}/${year}`; } // 原有的业务逻辑 }
内容的提问来源于stack exchange,提问作者John Doe
相关产品推荐
相关产品推荐

