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
になっています。
フォーマットを変えたい!
何かフォーマットを指定する手段はないものか?
ロケールを指定
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}}
が、実際の値を表示しているようです。
これを追っていくと...
-
*ngFor="let item of row;
- item は row の要素
-
*ngFor="let row of rows;
- row は rows の要素
- rows はHTML上から見つからなかったので ts 側で変数となっているはず
- https://github.com/angular/material2/blob/master/src/lib/datepicker/calendar-body.ts#L52
- ありました。
selector: '[mat-calendar-body]'
の@Input() rows: MatCalendarCell[][];
のようですね。
@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() {
}
}
最後にmemo
上記 Stack Overflow を見ると MD_DATE_FORMATS
をいじったり
NativeDateAdapter の format()
をオーバーライドしたりしている。
いまいち良くわからないまま試してみたものの、上手くいかず今回の方法に落ち着きました。
何かしら使うかもしれないので、とりあえずリンクだけ残す。
特に format は yyyy/MM/dd
な形式にするときに使いそうだ。