前言

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

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

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

自定义日期格式

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

  1. <mat-form-field>
  2. <input matInput [matDatepicker]="dp" placeholder="Verbose datepicker" [formControl]="date">
  3. <mat-datepicker-toggle matSuffix [for]="dp"></mat-datepicker-toggle>
  4. <mat-datepicker #dp></mat-datepicker>
  5. </mat-form-field>
  1. import {Component} from '@angular/core';
  2. import {FormControl} from '@angular/forms';
  3. import {MomentDateAdapter} from '@angular/material-moment-adapter';
  4. import {DateAdapter, MAT_DATE_FORMATS, MAT_DATE_LOCALE} from '@angular/material/core';
  5. // Depending on whether rollup is used, moment needs to be imported differently.
  6. // Since Moment.js doesn't have a default export, we normally need to import using the `* as`
  7. // syntax. However, rollup creates a synthetic default module and we thus need to import it using
  8. // the `default as` syntax.
  9. import * as _moment from 'moment';
  10. // tslint:disable-next-line:no-duplicate-imports
  11. import {default as _rollupMoment} from 'moment';
  12. const moment = _rollupMoment || _moment;
  13. // See the Moment.js docs for the meaning of these formats:
  14. // https://momentjs.com/docs/#/displaying/format/
  15. export const MY_FORMATS = {
  16. parse: {
  17. dateInput: 'LL',
  18. },
  19. display: {
  20. dateInput: 'LL',
  21. monthYearLabel: 'MMM YYYY',
  22. dateA11yLabel: 'LL',
  23. monthYearA11yLabel: 'MMMM YYYY',
  24. },
  25. };
  26. /** @title Datepicker with custom formats */
  27. @Component({
  28. selector: 'datepicker-formats-example',
  29. templateUrl: 'datepicker-formats-example.html',
  30. styleUrls: ['datepicker-formats-example.css'],
  31. providers: [
  32. // `MomentDateAdapter` can be automatically provided by importing `MomentDateModule` in your
  33. // application's root module. We provide it at the component level here, due to limitations of
  34. // our example generation script.
  35. {provide: DateAdapter, useClass: MomentDateAdapter, deps: [MAT_DATE_LOCALE]},
  36. {provide: MAT_DATE_FORMATS, useValue: MY_FORMATS},
  37. ],
  38. })
  39. export class DatepickerFormatsExample {
  40. date = new FormControl(moment());
  41. }

效果如下:

Datepicker自定义日期格式 - 图1

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

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

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

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

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

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

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

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

运行效果如下:

Datepicker自定义日期格式 - 图2

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

总结

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