Posted at

Angular Material の "Datepicker" の見た目と戦う

More than 1 year has passed since last update.

Angular Material で Datepicker を使おうとした時のお話です。

Angular 自体は 4 です。

Datepicker の Document は以下。

https://material.angular.io/components/datepicker/overview

デフォルトだと以下の絵のように <input> に表示されるテキストが M/d/yyyy になるようです。

更に曜日の表記も馴染みがない。

この見た目を変更するべく調査したのです。


まずは、デフォルト状態

<md-form-field>

<input mdInput [mdDatepicker]="picker" placeholder="Choose a date">
<md-datepicker-toggle mdSuffix [for]="picker"></md-datepicker-toggle>
<md-datepicker #picker></md-datepicker>
</md-form-field>

そのままコピペしたわけですが、

最初の絵のように普通に使える Datepicker なのですが、

<input> に表示されるテキストが M/d/yyyy になっています。

フォーマットを変えたい!

何かフォーマットを指定する手段はないものか?


ロケールを指定

https://material.angular.io/components/datepicker/overview#setting-the-locale-code

  import { Component, OnInit } from '@angular/core';

+ import { DateAdapter, NativeDateAdapter } from '@angular/material';

@Component({
selector: 'datepicker-example',
templateUrl: './datepicker-example.component.html',
styleUrls: ['./datepicker-example.component.css']
})
export class DatepickerExampleComponent implements OnInit {

- constructor() {
+ constructor(dateAdapter: DateAdapter<NativeDateAdapter>) {
+ dateAdapter.setLocale('de-DE');
}

ngOnInit() {
}
}

最初に見つけたのはロケール指定。

日本っぽいカレンダーになってくれるだろうか?

ということで早速やってみる。

もちろん dateAdapter.setLocale('ja'); である。

こんな感じの絵になった。

yyyy/M/d のようであるが良い感じだ。

曜日も 日 月 火... と良い感じだ。

ついでに Year の表記も SEP 2017 から 2017年9月 に、

Month の表記も SEP から 9月 に変わって日本らしくなった。

しかし、全部の日にちに "日" が付いている・・・。

なんとも気持ち悪い。

(執筆時には見慣れてて気持ち悪さ半減しておりましたが...)

これより先を弄るとなると Provider を上書きしてやる必要がありそうです。

https://material.angular.io/components/datepicker/overview#customizing-the-date-implementation

https://material.angular.io/components/datepicker/overview#customizing-the-parse-and-display-formats

https://material.angular.io/components/datepicker/overview#localizing-labels-and-messages


とりあえず Google Developer Tools

mat-calendar-body-cell-content か...


calendar-body っぽいところを探す

https://github.com/angular/material2/blob/master/src/lib/datepicker/calendar-body.html#L42

にありました。

どうやら {{item.displayValue}} が、実際の値を表示しているようです。

これを追っていくと...

@Input() ということは、どこかで設定している人がいるはず!


mat-calendar-body の [rows] を探す

https://github.com/angular/material2/blob/master/src/lib/datepicker/month-view.html#L9

にいました。

次は _weeks だ!

さっきと同じく ts 側にいるはずだ!


_weeks を探す

https://github.com/angular/material2/blob/master/src/lib/datepicker/month-view.ts#L171

ここで値を突っ込んでいました。

おもむろに console.log(dateNames[i]) をしてみると...



CHIBI: 1日

CHIBI: 2日

CHIBI: 3日

CHIBI: 4日

CHIBI: 5日

それっぽい!

dateNames[i] の代わりに適当な文字列を入れてみても...

これだ...!!

dateNames は以下のコードで取得されている。

https://github.com/angular/material2/blob/master/src/lib/datepicker/month-view.ts#L157

DateAdapter が出てきた。

さっきさらっと流した Provider 上書きの出番!

https://material.angular.io/components/datepicker/overview#customizing-the-date-implementation


Provider 上書き

  import { Component, OnInit } from '@angular/core';

import { DateAdapter, NativeDateAdapter } from '@angular/material';

+ class MyDateAdapter extends NativeDateAdapter {
+ getDateNames(): string[] {
+ const dateNames: string[] = [];
+ for (let i = 0; i < 31; i++) {
+ dateNames[i] = String(i + 1);
+ }
+ return dateNames;
+ }
+ }

@Component({
selector: 'datepicker-example',
templateUrl: './datepicker-example.component.html',
styleUrls: ['./datepicker-example.component.css'],
+ providers: [
+ {provide: DateAdapter, useClass: MyDateAdapter}
+ ]
})
export class DatepickerExampleComponent implements OnInit {

constructor(dateAdapter: DateAdapter<NativeDateAdapter>) {
dateAdapter.setLocale('ja');
}

ngOnInit() {
}
}


:tada::tada::tada:


最後にmemo

https://stackoverflow.com/questions/44452966/angular-2-material-2-datepicker-date-format

上記 Stack Overflow を見ると MD_DATE_FORMATS をいじったり

NativeDateAdapter の format() をオーバーライドしたりしている。

いまいち良くわからないまま試してみたものの、上手くいかず今回の方法に落ち着きました。

何かしら使うかもしれないので、とりあえずリンクだけ残す。

特に format は yyyy/MM/dd な形式にするときに使いそうだ。