やりたいこと:
・AngularMaterialのDatepickerを使って年情報はいらないからstringで"5月28日"とかで取得したい
・画像のように年情報は選べないようにしたい
やること:
・pickerのヘッダー部分のカスタム
・取得した情報をstringにフォーマット
参考
前準備
MomentDateAdapterとmomentのインストール
npm i moment
npm i @angular/material-moment-adapter
カスタムするヘッダーのコンポーネントを作る
ng g c form-part/custom-header
フォルダ名やコンポーネント名はなんでもいいよ
@NgModule({
declarations: [CustomHeaderComponent],
imports: [...省略...],
exports: [...省略...],
entryComponents: [CustomHeaderComponent],
})
module.tsでentryComponentsに追加するのを忘れないように
CustomHeaderComponent
<div class="custom-datepicker-header">
<span class="material-icons" (click)="previousClicked('month')">
keyboard_arrow_left
</span>
<span class="custom-datepicker-label">{{ periodLabel }}</span>
<span class="material-icons" (click)="nextClicked('month')">
keyboard_arrow_right
</span>
</div>
.custom-datepicker-header {
display: flex;
align-items: center;
padding: 0.5em;
}
.custom-datepicker-label {
flex: 1;
height: 1em;
font-weight: 500;
text-align: center;
}
import {
ChangeDetectionStrategy,ChangeDetectorRef,Component,Inject,OnDestroy,
} from "@angular/core";
import { MatCalendar } from "@angular/material/datepicker";
import {
DateAdapter,MAT_DATE_FORMATS,MatDateFormats,
} from "@angular/material/core";
import { Subject } from "rxjs";
import { takeUntil } from "rxjs/operators";
@Component({
selector: "app-custom-header",
templateUrl: "./custom-header.component.html",
styleUrls: ["./custom-header.component.scss"],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class CustomHeaderComponent implements OnDestroy {
private _destroyed = new Subject<void>();
constructor(
private _calendar: MatCalendar<any>,
private _dateAdapter: DateAdapter<any>,
@Inject(MAT_DATE_FORMATS) private _dateFormats: MatDateFormats,
cdr: ChangeDetectorRef
) {
_calendar.stateChanges
.pipe(takeUntil(this._destroyed))
.subscribe(() => cdr.markForCheck());
_dateAdapter.setLocale("ja"); //日本語にする
}
ngOnDestroy() {
this._destroyed.next();
this._destroyed.complete();
}
get periodLabel() { // 選択中の月を返す
return this._dateAdapter
.format(
this._calendar.activeDate,
this._dateFormats.display.monthYearLabel
)
.toLocaleUpperCase();
}
previousClicked(mode: any) { // 前の月を表示
this._calendar.activeDate = this._dateAdapter.addCalendarMonths(
this._calendar.activeDate,
-1
);
}
nextClicked(mode: any) { // 次の月を表示
this._calendar.activeDate = this._dateAdapter.addCalendarMonths(
this._calendar.activeDate,
1
);
}
}
カスタムしたヘッダーを設定する
datepickerを設置するコンポーネント
<mat-form-field>
<mat-label>Choose a date</mat-label>
<input matInput [matDatepicker]="picker" />
<mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
<mat-datepicker #picker [calendarHeaderComponent]="header"></mat-datepicker>
</mat-form-field>
import { ChangeDetectionStrategy, Component } from "@angular/core";
import {
DateAdapter, MAT_DATE_FORMATS, MAT_DATE_LOCALE,
} from "@angular/material/core";
import {
MomentDateAdapter,MAT_MOMENT_DATE_ADAPTER_OPTIONS,
} from "@angular/material-moment-adapter";
import { CustomHeaderComponent } from "../../form-part/custom-header/custom-header.component";
export const MY_FORMATS = {
parse: {
dateInput: "DD/MMM",
},
display: {
dateInput: "MM月DD日",
monthYearLabel: "MMM",
dateA11yLabel: "LL",
monthYearA11yLabel: "MMMM YYYY",
},
};
@Component({
selector: "app-date-picker",
templateUrl: "./date-picker.component.html",
styleUrls: ["./date-picker.component.scss"],
changeDetection: ChangeDetectionStrategy.OnPush,
providers: [
{
provide: DateAdapter,
useClass: MomentDateAdapter,
deps: [MAT_DATE_LOCALE, MAT_MOMENT_DATE_ADAPTER_OPTIONS],
},
{ provide: MAT_DATE_FORMATS, useValue: MY_FORMATS },
],
})
export class DatePickerComponent {
header = CustomHeaderComponent;
constructor() {}
}
[calendarHeaderComponent]で作ったカスタムコンポーネントを指定する
これで月と日だけが選べるdatepickerの完成。
datepickerにformControlを設定してvalueを確認してみましょう
export class DatePickerComponent implements OnInit {
header = CustomHeaderComponent;
date = new FormControl();
constructor() {}
ngOnInit() {}
output() {
console.log(this.date.value);
}
}
<mat-form-field>
<mat-label>Choose a date</mat-label>
<input
matInput
[matDatepicker]="picker"
[formControl]="date"
(dateChange)="output()"
/>
<mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
<mat-datepicker #picker [calendarHeaderComponent]="header"></mat-datepicker>
</mat-form-field>
Momentで取得できているので formatします
output() {
let Moment = this.date.value as moment.Moment;
console.log(Moment.format("MM月DD日"));
}
おそらくprovider:DateAdapterに指定するクラスを自作すれば
モーメントじゃなくて直接MM月DD日の形でvalue取得できると思いますが
それはまた別の機会に検討してみようと思います。