Angular Material日期选择器:如何在验证前直接转为yyyy-MM-dd格式?
问题
我正在开发一个使用Angular Material Datepicker的应用,该日期选择器返回ISO 8601格式的Date对象,我需要将其转换为yyyy-MM-dd格式的字符串。目前我通过日期选择器的closed事件触发转换函数,但自定义校验器会在该函数执行前触发,导致校验逻辑异常。
相关代码如下:
HTML代码
<mat-form-field class="example-full-width" appearance="fill"> <mat-label>{{ 'commons.consultations.dateTo' | translate }}</mat-label> <input matInput [matDatepicker]="pickerTo" formControlName="dateTo" /> <mat-datepicker-toggle matSuffix [for]="pickerTo" ></mat-datepicker-toggle> <mat-datepicker (closed)="convertDateTo_YYYY_MM_DD_Format()" #pickerTo ></mat-datepicker> </mat-form-field>
TypeScript代码
public convertDateTo_YYYY_MM_DD_Format() { this.form .get('dateTo') ?.setValue( this.datePipe.transform(this.form.get('dateTo')?.value, 'yyyy-MM-dd') ); }
Module配置(fr-FR格式)
providers: [{ provide: MAT_DATE_LOCALE, useValue: 'fr-FR' }, DatePipe]
自定义校验器
export function dateValidator( dateTo: string, ): ValidatorFn { return (form: AbstractControl): ValidationErrors | null => { let dateToControl = form.get(dateTo); const regEx = /^[12]\d{3}-\d{2}-\d{2}$/; // 省略其他逻辑 if (dateToControl.value?.match(regEx)) { // 执行相关操作 } // 返回校验结果 return null; } }
请问是否有办法让日期选择器本身直接将日期转换为yyyy-MM-dd格式,无需依赖closed事件,从而在校验器触发前完成转换?
解决方案
可以通过配置Angular Material的MAT_DATE_FORMATS让日期选择器直接输出yyyy-MM-dd格式的字符串,从根源上解决校验器触发时机的问题,无需依赖closed事件转换。
步骤1:定义自定义日期格式常量
在项目中创建一个日期格式配置文件(比如date-formats.ts),或直接在模块文件中定义:
import { MAT_DATE_FORMATS } from '@angular/material/core'; export const CUSTOM_DATE_FORMATS = { parse: { dateInput: 'yyyy-MM-dd', // 配置解析时使用的格式 }, display: { dateInput: 'yyyy-MM-dd', // 配置输入框显示和返回的格式 monthYearLabel: 'MMM yyyy', dateA11yLabel: 'yyyy-MM-dd', monthYearA11yLabel: 'MMMM yyyy', }, };
步骤2:在模块中注入自定义格式
修改模块文件,在providers数组中添加MAT_DATE_FORMATS配置,保留原有的MAT_DATE_LOCALE配置:
import { NgModule } from '@angular/core'; import { MAT_DATE_LOCALE, MAT_DATE_FORMATS } from '@angular/material/core'; import { CUSTOM_DATE_FORMATS } from './date-formats'; // 其他必要导入 @NgModule({ // 其他配置项 providers: [ { provide: MAT_DATE_LOCALE, useValue: 'fr-FR' }, { provide: MAT_DATE_FORMATS, useValue: CUSTOM_DATE_FORMATS }, DatePipe ] }) export class YourModule { }
步骤3:移除原有转换逻辑
现在日期选择器会自动将选中日期转换为yyyy-MM-dd格式的字符串并赋值给FormControl,因此可以删除以下内容:
- HTML中的
(closed)="convertDateTo_YYYY_MM_DD_Format()"绑定 - TypeScript中的
convertDateTo_YYYY_MM_DD_Format方法
原理说明
Angular Material Datepicker通过DateAdapter和MAT_DATE_FORMATS处理日期的解析与显示。配置自定义格式后,Datepicker会在用户选择日期时,提前将Date对象转换为指定格式的字符串,这个转换过程早于校验器触发时机,因此校验器拿到的直接是符合要求的yyyy-MM-dd格式字符串,不会再出现逻辑异常。
内容的提问来源于stack exchange,提问作者Olivier

