乐趣区

Material-Datepicker自定义日期格式

前言

在企业级开发中,我们经常会使用到日期控件。在以前的 jquery 框架项目中,我们通常会选择 mydate 97。现在我们使用 Angular 框架,Material 官网也为我们提供了 Datepicker 组件。对于日期的显示的格式,有很多种,比如下面的:

  • 2019/07/11
  • 2019-07-11
  • 等 …

面对这种需求,就需要我们可以自定义 Datepicker 的显示格式。

自定义日期格式

官网为我们提供了一个自定义格式的范例:

<mat-form-field>
  <input matInput [matDatepicker]="dp" placeholder="Verbose datepicker" [formControl]="date">
  <mat-datepicker-toggle matSuffix [for]="dp"></mat-datepicker-toggle>
  <mat-datepicker #dp></mat-datepicker>
</mat-form-field>
import {Component} from '@angular/core';
import {FormControl} from '@angular/forms';
import {MomentDateAdapter} from '@angular/material-moment-adapter';
import {DateAdapter, MAT_DATE_FORMATS, MAT_DATE_LOCALE} from '@angular/material/core';

// Depending on whether rollup is used, moment needs to be imported differently.
// Since Moment.js doesn't have a default export, we normally need to import using the `* as`
// syntax. However, rollup creates a synthetic default module and we thus need to import it using
// the `default as` syntax.
import * as _moment from 'moment';
// tslint:disable-next-line:no-duplicate-imports
import {default as _rollupMoment} from 'moment';

const moment = _rollupMoment || _moment;

// See the Moment.js docs for the meaning of these formats:
// https://momentjs.com/docs/#/displaying/format/
export const MY_FORMATS = {
  parse: {dateInput: 'LL',},
  display: {
    dateInput: 'LL',
    monthYearLabel: 'MMM YYYY',
    dateA11yLabel: 'LL',
    monthYearA11yLabel: 'MMMM YYYY',
  },
};

/** @title Datepicker with custom formats */
@Component({
  selector: 'datepicker-formats-example',
  templateUrl: 'datepicker-formats-example.html',
  styleUrls: ['datepicker-formats-example.css'],
  providers: [
    // `MomentDateAdapter` can be automatically provided by importing `MomentDateModule` in your
    // application's root module. We provide it at the component level here, due to limitations of
    // our example generation script.
    {provide: DateAdapter, useClass: MomentDateAdapter, deps: [MAT_DATE_LOCALE]},

    {provide: MAT_DATE_FORMATS, useValue: MY_FORMATS},
  ],
})
export class DatepickerFormatsExample {date = new FormControl(moment());
}

效果如下:

在这个官方范例中,使用到了 moment 这个库,因此我们在 npm 包管理中加入 moment 依赖。

接下来我们分析这个例子。

可以看看到在 TypeScript 文件中,定义了个 MY_FORMATS 的常量:

// See the Moment.js docs for the meaning of these formats:
// https://momentjs.com/docs/#/displaying/format/
export const MY_FORMATS = {
  parse: {dateInput: 'LL',  // 表示 input 中输入的格式,moment 将按此格式解析内容},
  display: {
    dateInput: 'LL',  // 显示格式,monent 将日期按此格式呈现给用户
    monthYearLabel: 'MMM YYYY',
    dateA11yLabel: 'LL',
    monthYearA11yLabel: 'MMMM YYYY',
  },
};
providers: [
    // `MomentDateAdapter` can be automatically provided by importing `MomentDateModule` in your
    // application's root module. We provide it at the component level here, due to limitations of
    // our example generation script.
    {provide: DateAdapter, useClass: MomentDateAdapter, deps: [MAT_DATE_LOCALE]},

    {provide: MAT_DATE_FORMATS, useValue: MY_FORMATS},
  ],

通过使用 Providers,将 MY_FORMATS 注册成服务,这样 Angular 就可以通过 DI 将 MAT_DATE_FORMATS 注入给 Datepicker 组件了。

那么像我们上面提到的 2019-07-11 该如何自定义呢?

要实现这个格式还是比较简单的,我们只需要修改 MY_FORMATS,其他的内容不需要动,就可以实现我们想要的效果:

// See the Moment.js docs for the meaning of these formats:
// https://momentjs.com/docs/#/displaying/format/
export const MY_FORMATS = {
  parse: {dateInput: 'YYYY-MM-DD',  // 表示 input 中输入的格式,moment 将按此格式解析内容},
  display: {
    dateInput: 'YYYY-MM-DD',  // 显示格式,monent 将日期按此格式呈现给用户
    monthYearLabel: 'MMM YYYY',
    dateA11yLabel: 'LL',
    monthYearA11yLabel: 'MMMM YYYY',
  },
};

运行效果如下:

需要注意的是,我们要确保 parse>dateInput 和 diplay>dateInput 的格式保持一致。

总结

Material Datepicker 目前还没有支持像 mydate 97 那样强大。如果需要在同一个表单中,多个 input 显示不同的日期格式,就需要使用 Angular 的组件化特性,把每一种格式的日期封装成一个独立的组件,每个组件使用自己的 Provider,这样就可以在同一个表单中使用多个自定义组件,实现不同日期格式的需求。

退出移动版