2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【AngularMaterial】月と日情報だけ取得するdatepicker

Posted at

やりたいこと:

・AngularMaterialのDatepickerを使って年情報はいらないからstringで"5月28日"とかで取得したい
・画像のように年情報は選べないようにしたい
スクリーンショット 2020-05-29 14.11.30.png

やること:

・pickerのヘッダー部分のカスタム
・取得した情報をstringにフォーマット

参考

StackBlitz

前準備

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]で作ったカスタムコンポーネントを指定する

スクリーンショット 2020-05-29 14.11.30.png

これで月と日だけが選べる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>

日付を選択したらコンソールにvalueを出力します
スクリーンショット 2020-05-29 15.59.37.png

Momentで取得できているので formatします

  output() {
    let Moment = this.date.value as moment.Moment;
    console.log(Moment.format("MM月DD日"));
  }

スクリーンショット 2020-05-29 16.07.56.png
目的の形になりました。

おそらくprovider:DateAdapterに指定するクラスを自作すれば
モーメントじゃなくて直接MM月DD日の形でvalue取得できると思いますが
それはまた別の機会に検討してみようと思います。

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?