You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular Material日期选择器获取字符串而非对象toString值的解决方案

解决Angular Material Datepicker组件表单取值为日期对象toString的问题

你当前的问题源于matDatepicker绑定的是原生Date对象,ngModelChange触发时传递的是Date实例,表单最终存储该对象后,调用toString()就会得到类似Wed May 10 2023 00:00:00 GMT+0200的结果。以下是无需依赖已废弃Moment.js的两种替代方案:

方案1:使用Angular内置DatePipe格式化输出

Angular自带的DatePipe可直接完成日期格式化,步骤如下:

  1. 在组件中注入DatePipe
  2. 修改ngModelChange处理逻辑,将Date对象格式化为目标字符串后再传递给onChange
  3. 处理writeValue方法,将传入的格式化字符串转回Date对象用于回显

修改后的TypeScript代码

import { Component, forwardRef, Input } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
import { DatePipe } from '@angular/common';

@Component({
  selector: 'm6smart-form-datepicker',
  templateUrl: './form-datepicker.component.html',
  styleUrls: ['./form-datepicker.component.scss'],
  providers: [
    DatePipe,
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => FormDatepickerComponent),
      multi: true,
    },
  ],
})
export class FormDatepickerComponent implements ControlValueAccessor {
  @Input() formInput!: FormDatepickerInput;

  onChange: any = () => {};
  onTouch: any = () => {};
  value: Date | string | undefined; // 调整类型兼容Date和字符串
  disabled: boolean = false;
  private readonly dateFormat = 'yyyy-MM-dd'; // 定义目标格式

  constructor(private datePipe: DatePipe) {}

  writeValue(obj: any): void {
    // 回显时将字符串转为Date对象
    this.value = typeof obj === 'string' ? new Date(obj) : obj;
  }

  registerOnChange(fn: any): void {
    this.onChange = fn;
  }

  registerOnTouched(fn: any): void {
    this.onTouch = fn;
  }

  setDisabledState(isDisabled: any): void {
    this.disabled = isDisabled;
  }

  // 处理日期变更,格式化后传递给表单
  onDateChange(event: Date): void {
    const formattedDate = this.datePipe.transform(event, this.dateFormat);
    this.onChange(formattedDate);
    this.value = event;
    this.onTouch();
  }
}

修改后的HTML代码

将ngModelChange绑定到自定义处理方法:

<mat-form-field (click)="picker.open()" appearance="fill">
  <mat-label>{{ formInput.label }}</mat-label>
  <input 
    matInput 
    [matDatepicker]="picker" 
    [(ngModel)]="value" 
    (ngModelChange)="onDateChange($event)" 
    [required]="formInput.required" 
    [disabled]="formInput.disabled || disabled" 
    autocomplete="off" 
  />
  <mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
  <mat-datepicker #picker [disabled]="formInput.disabled || disabled"></mat-datepicker>
</mat-form-field>

方案2:自定义日期适配器与格式器(全局统一格式)

若需在整个应用中统一日期格式,推荐使用Angular Material提供的DateAdapter和MAT_DATE_FORMATS,完全基于原生Date实现:

1. 创建自定义日期适配器

import { NativeDateAdapter } from '@angular/material/core';

export class CustomDateAdapter extends NativeDateAdapter {
  override format(date: Date, displayFormat: Object): string {
    // 定义全局输出格式
    const year = date.getFullYear();
    const month = this._twoDigit(date.getMonth() + 1);
    const day = this._twoDigit(date.getDate());
    return `${year}-${month}-${day}`;
  }

  private _twoDigit(num: number): string {
    return num < 10 ? '0' + num : num.toString();
  }
}

2. 配置自定义日期格式

import { MAT_DATE_FORMATS } from '@angular/material/core';

export const CUSTOM_DATE_FORMATS = {
  parse: {
    dateInput: 'yyyy-MM-dd', // 解析输入的格式
  },
  display: {
    dateInput: 'yyyy-MM-dd', // 输入框显示的格式
    monthYearLabel: 'yyyy MMM',
    dateA11yLabel: 'yyyy-MM-dd',
    monthYearA11yLabel: 'yyyy MMMM',
  },
};

3. 在模块中提供配置

在共享组件所在模块添加提供者:

import { NgModule } from '@angular/core';
import { MAT_DATE_FORMATS, DateAdapter } from '@angular/material/core';
import { CustomDateAdapter } from './custom-date-adapter';
import { CUSTOM_DATE_FORMATS } from './custom-date-formats';

@NgModule({
  ...
  providers: [
    { provide: DateAdapter, useClass: CustomDateAdapter },
    { provide: MAT_DATE_FORMATS, useValue: CUSTOM_DATE_FORMATS },
    // 可选:设置本地化,如中文
    // { provide: MAT_DATE_LOCALE, useValue: 'zh-CN' }
  ],
})
export class SharedModule {}

4. 调整组件逻辑

此时ngModelChange会直接返回格式化后的字符串,只需确保writeValue兼容字符串和Date对象:

writeValue(obj: any): void {
  this.value = typeof obj === 'string' ? new Date(obj) : obj;
}

内容的提问来源于stack exchange,提问作者Mark116

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 10:14:57