How to change output format of material 2 date-pic

2020-02-10 09:19发布

I am using angular material 2 Date-Picker component

The only string input it understands is in ISO date format

Ex. "2017-11-13T10:39:28.300Z"

But i want to patch my form control with locale date value

Ex. "11/13/2017, 4:09:46 PM"

So that it output the later format and even expects this format.

How can i do this? Is there a way to not use ISO but custom formats?

Some Thoughts:

Should i write customDateAdaptor?

Update:

https://stackblitz.com/edit/angular-material-moment-adapter-example-bqvm2f

i have tried to implement custom dateAdaptor by extending nativeDateAdaptor

7条回答
Summer. ? 凉城
2楼-- · 2020-02-10 09:31

You need to create a class extending NativeDateAdapter (from "@angular/material/core")

If you override the format function you will change the way the date is displayed on the input after selecting a date. The parse function is called when you edit the input value manually, to display a valid date.

See the 2nd comment for more details: https://github.com/angular/material2/issues/5722

EDIT:

I couldn't find a way to format the output so I've wrapped the material datepicker component to a custom component.

This custom component has a 2 way binding on a property to get the date: @Input() selectedValue and @Output() selectedValueChange: EventEmitter<any> = new EventEmitter<any>();

A private _selectedValue; is set on ngInit, it will contain the datepicker date.

Then in the template, the html datepicker input element has [(ngModel)]="_selectedValue" (dateChange)="onChange($event)"

The onChange function gets the datepicker value _selectedValue, formats it and emit it to selectedValueChange.

The final component looks like this:

import { Component, OnInit, Input, Output, EventEmitter } from "@angular/core";
import {
  DateAdapter,
  NativeDateAdapter,
  MAT_DATE_FORMATS,
  MAT_DATE_LOCALE
} from "@angular/material/core";
import * as moment from "moment";

const CUSTOM_DATE_FORMATS = {
  parse: {
    dateInput: { month: "short", year: "numeric", day: "numeric" }
  },
  display: {
    dateInput: "input",
    monthYearLabel: { year: "numeric", month: "short" },
    dateA11yLabel: { year: "numeric", month: "long", day: "numeric" },
    monthYearA11yLabel: { year: "numeric", month: "long" }
  }
};
const dateFormat = "YYYY-MM-DD";
// date adapter formatting material2 datepickers label when a date is selected
class AppDateAdapter extends NativeDateAdapter {
  format(date: Date, displayFormat: Object): string {
    if (displayFormat === "input") {
      return moment(date).format(dateFormat);
    } else {
      return date.toDateString();
    }
  }
}
@Component({
  selector: "datepicker",
  templateUrl: "./datepicker.component.html",
  styleUrls: ["./datepicker.component.scss"],
  providers: [
    { provide: MAT_DATE_FORMATS, useValue: CUSTOM_DATE_FORMATS },
    { provide: DateAdapter, useClass: AppDateAdapter }
  ]
})
export class DatepickerComponent implements OnInit {
  @Input() placeholder;
  @Output() onFilter: EventEmitter<any> = new EventEmitter<any>();
  @Input() selectedValue;
  @Output() selectedValueChange: EventEmitter<any> = new EventEmitter<any>();

  private _selectedValue;
  constructor() {}

  ngOnInit() {
    this._selectedValue = this.selectedValue;
  }

  onChange($event) {
    this.selectedValue = this.updateDate($event.value);
    this.onFilter.emit(this.selectedValue);
  }

  updateDate(date) {
    let formatedDate;
    if (date !== undefined) {
      formatedDate = moment(date).format(dateFormat);
    }
    this.selectedValueChange.emit(formatedDate);
    return formatedDate;
  }
}
查看更多
smile是对你的礼貌
3楼-- · 2020-02-10 09:32

you can call Emitter of this module (for example click event) and change model binded to this module to secondary model.

查看更多
小情绪 Triste *
4楼-- · 2020-02-10 09:33

First import moment and set format . https://momentjs.com/

 import * as moment from 'moment';

setDateFormat(date) {
    this.myDate = moment(date).format('YYYY/MM/DD HH:mm:ss');
  }
查看更多
▲ chillily
5楼-- · 2020-02-10 09:35

Not sure, if you are already doing this but I found some information that might give you some idea on your implementation.

As of today the Angular Material Date Module supports two ways of providing a date value MatNativeDateModule and MatMomentDateModule. The MatNativeDateModule accepts ISO 8601 format by default. But since you don't want to use ISO format, I would suggest using MatMomentDateModule (Moment.js implementation).

When we use the MatMomentDateModule the date object is not anymore a JavaScript Date object but instead is a Moment.js instance(take advantage of methods available to a Moment js instance like format()). There are basic to intermediate examples available on Material Date Picker docs page using the Moment.js. Also, once your date is a Moment.js instance, you could overwrite the methods(format, parse.) from MomentDateAdapter instead of native date adapter.

查看更多
Viruses.
6楼-- · 2020-02-10 09:37

You probably need to write a completely new adapter or use the moment adapter. @angular/material-moment-adapter:5.0.0-rc0. The moment adapter uses momentjs and allows you much more control on the output format.

Moment is also able to parse different input formats.

The NativeDateAdapter uses the Intl API to format the output date. You can try to provide a custom MAT_NATIVE_DATE_FORMATS instance but I am not sure how far this gets you.

EDIT

You are currently using 2.0.0-beta12 of angular/material, that doesn't fit with your code based on 5.0.0-rc0/master. There are changes in the codebase, especially the deserialize function which is not present in 2.0.0-beta12, that's why it is not being called. If you can't update to angular 5 then look at MatDatepickerInput.setValue/coerceDateProperty which sets the date into your FormControl.

查看更多
Ridiculous、
7楼-- · 2020-02-10 09:44

The best solution would be to use ControlValueAccessor and make a custom input component, this will have you in control of input and output of the component.

update:

Here is the reference implementation using this approach reproduced by Moutaz-homsi

https://stackblitz.com/edit/angular-dlxnmx?file=app%2Fcva-date.component.ts

查看更多
登录 后发表回答