Angular 10の新機能「日付範囲ピッカー」を試してみた

普段のお仕事に役立つ普遍的なプログラミングTIPSや、業界で注目度が高い最新情報をお届けする「編集部ピックアップ」。
今回は「Angular 10」で追加されたAngular Materialの「日付範囲ピッカー」についてお届けします。

フロントエンドJavaScriptフレームワーク「Angular」では現在、メジャーバージョンとして2020年6月末にリリースされた10系が利用可能です。

Angular 10では、さまざまな面で改良が加えられていますが、今回はその中からAngular Materialに新しく追加された日付範囲ピッカーをご紹介したいと思います。

Angular 10について

Angular 10は、リリースが遅れたAngular 9のリリースからわずか4カ月でリリースされました。このメジャーバージョンアップでは、この記事で紹介する日付範囲ピッカーの他にも以下のような変更が行われています。

  • CommonJSインポートに関する警告
  • strictオプションによる厳格な設定
  • エコシステムの最新化
  • 新しいデフォルトのブラウザ設定

この中でも特に、エコシステムを最新に保つための変更と、デフォルトブラウザの設定変更には注意しておきましょう。

Angular 10になってから、利用されているTypeScriptは3.9へ変更されTSLintはv6に変わっています。また、デフォルトブラウザに対しては、古いブラウザやあまり利用されていないブラウザの除外が行われており、全体的に対応しているブラウザが整理されています。

このようなバージョン関連の変更は予期せぬエラーの原因になる可能性があるため、適切に対応するようにしましょう。

Angular Materialとは

Angular Materialは、Angularで利用できるコンポーネントで、Angularの開発の中心であるGoogleが提唱しているMaterial Designに基づいた設計となっています。提供されているコンポーネントを組み合わせることで効率的にUIを組み立てることが可能です。

入力やボタン、カードなど使用頻度の高いコンポーネントから、プログレススピナーやステッパーなどよりリッチなUIのコンポーネントまで、さまざなものが提供されています。

今回Angular 10で追加された日付範囲ピッカーは、Angular 9以前から提供されていた日付ピッカーの一部として利用可能になっています。

Angular Materialのインストール

日付範囲ピッカーの説明の前に、まずはAngular Materialの使い方を紹介したいと思います。

こちらを参考に新しいAngularアプリケーションを作成したら、コンソールなどから以下のコマンドを実行してAngular Materialをインストールします。途中、使用するテーマや、アニメーションの有効化について確認されますが、今回はすべてデフォルトの設定で進めます。

ng add @angular/material

日付ピッカーの使い方

Angular Materialの日付ピッカーは、「Input」や「Form Field」などいくつかの別のコンポーネントやディレクティブと共に機能します。app/app.module.tsに以下を追加して、必要なコンポーネントをインポートします。

import {MatFormFieldModule} from '@angular/material/form-field';
import {MatInputModule} from '@angular/material/input';
import {MatDatepickerModule} from '@angular/material/datepicker';
import {MatNativeDateModule} from '@angular/material/core';
・
・
・
imports: [
・
・
MatFormFieldModule,
MatInputModule,
MatDatepickerModule,
MatNativeDateModule
],

app/app.component.htmlの内容を以下に書き換えます。

<mat-form-field appearance="fill" class="example-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></mat-datepicker>
</mat-form-field>

app/app.component.cssに以下を追加して、余白の設定を行います。

.example-form-field {
margin: 1em 0.5em 1.5em 1em;
}

以下のコマンドを実行して、アプリケーションを起動します。

ng serve --open

起動すると、以下のように日付ピッカーが表示されます。このコンポーネントで特徴的な部分は、入力とカレンダーのポップアップがmatDatepickerを介して統一されているところです。

カレンダーの表示はカスタマイズ可能で、一例として「startView」「[startAt]」を設定することで、カレンダーの初期表示の状態を変更できます。startViewには、monthyearmulti-yearが選択でき、デフォルトではmonthが設定されています。

app/app.component.htmlの中のmat-datepickerの記述を以下のように変更します。

<mat-datepicker #picker startView="year" [startAt]="startDate"></mat-datepicker>

また、app/app.component.tsに、以下のように初期表示する日付を定義します。今回はカレンダーを開いたときに2021年1月が最初に表示されるように設定します。

export class AppComponent {
startDate = new Date(2021, 0, 1);
}

初期表示をカスタマイズ

日付範囲ピッカーの使い方

ここから日付範囲ピッカーの紹介です。ユーザーに日付を一つだけではなく範囲で入力させたい場合、「mat-date-range-input」および「mat-date-range-picker」コンポーネントを使用します。これらはmat-datepickerと同じように機能します。

mat-date-range-inputコンポーネントではinputが2つの必要で、それぞれ開始日と終了日を指定します。app/app.component.htmlの内容を以下のように書き換えます。

<mat-form-field class="example-form-field" >
<mat-label>Enter a date range</mat-label>
<mat-date-range-input [rangePicker]="picker">
<input matStartDate matInput placeholder="Start date">
<input matEndDate matInput placeholder="End date">
</mat-date-range-input>
<mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
<mat-date-range-picker #picker></mat-date-range-picker>
</mat-form-field>

再度実行すると、以下のように日付の範囲入力が可能になります。

カレンダーを日本語化する

日付ピッカーは日本語ロケールの設定をすることで、日本のカレンダー書式でも表示できます。元々のロケールは「en-US」で設定されていますが、app/app.module.tsに以下を追加して、日本のロケールを設定できます。

import { MAT_DATE_LOCALE } from '@angular/material/core';
・
・
@NgModule({
・
・
providers: [
{provide: MAT_DATE_LOCALE, useValue: 'ja-JP'},
],

再度実行すると、以下のようにカレンダーが日本語化されます。

カレンダーを日本語化

ただし、この状態だと、日付にすべて「日」がくっついて表示されるのでちょっと微妙ですね…。これを解消するにはいくつか方法がありますが、日付操作ができる「momentライブラリ」を使用する方法をご紹介します。

まずは、以下の2つのパッケージをインストールします。

npm install moment
npm install @angular/material-moment-adapter

app/app.module.tsを以下のように修正します。

import { DateAdapter, MAT_DATE_FORMATS, MAT_DATE_LOCALE } from '@angular/material/core';
import { MAT_MOMENT_DATE_FORMATS, MomentDateAdapter } from '@angular/material-moment-adapter';
・
・
・
providers: [
{ provide: MAT_DATE_LOCALE, useValue: 'ja-JP' },
{ provide: DateAdapter, useClass: MomentDateAdapter, deps: [MAT_DATE_LOCALE] },
{ provide: MAT_DATE_FORMATS, useValue: MAT_MOMENT_DATE_FORMATS },
],
・
・

再度実行すると、以下のように日付に「日」の付かない日本語カレンダーが表示されます。

ただ、こちらもよく見ると、「9月 2020」のように、「年」と「月」の順番が入れ替わって表示されてしまうので、完璧ではないですね。他にもDateAdapterを継承してカスタムする方法など、カレンダーの日本語化にはいくつか方法があります。

2つの日付範囲を比較表示する

日付範囲ピッカーでは、日程の比較を行うことも簡単に行えます。旅行やイベントの日程を決める際によくみられるようなUIを非常に簡単に実装することができます。

app/app.module.tsに以下を追加します。

import { FormsModule, ReactiveFormsModule } from '@angular/forms';
・
・
@NgModule({
declarations: [
AppComponent
],
imports: [
・
・
・
FormsModule,
ReactiveFormsModule
],

app/app.module.tsを以下のように書き換えます。

import { Component } from '@angular/core';
import {FormGroup, FormControl} from '@angular/forms';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
campaignOne: FormGroup;
campaignTwo: FormGroup;
title = 'datepicker-sample';
constructor() {
const today = new Date();
const month = today.getMonth();
const year = today.getFullYear();
this.campaignOne = new FormGroup({
start: new FormControl(new Date(year, month, 13)),
end: new FormControl(new Date(year, month, 16))
});
this.campaignTwo = new FormGroup({
start: new FormControl(new Date(year, month, 15)),
end: new FormControl(new Date(year, month, 19))
});
}
}

app/app.component.htmlを以下のように書き換えます。

<mat-form-field class="example-form-field" appearance="fill">
<mat-label>First campaign</mat-label>
<mat-date-range-input
    [formGroup]="campaignOne"
    [rangePicker]="campaignOnePicker"
    [comparisonStart]="campaignTwo.value.start"
    [comparisonEnd]="campaignTwo.value.end">
<input matStartDate placeholder="Start date" formControlName="start">
<input matEndDate placeholder="End date" formControlName="end">
</mat-date-range-input>
<mat-datepicker-toggle matSuffix [for]="campaignOnePicker"></mat-datepicker-toggle>
<mat-date-range-picker #campaignOnePicker></mat-date-range-picker>
</mat-form-field>
<mat-form-field class="example-form-field" appearance="fill">
<mat-label>Second campaign</mat-label>
<mat-date-range-input
    [formGroup]="campaignTwo"
    [rangePicker]="campaignTwoPicker"
    [comparisonStart]="campaignOne.value.start"
    [comparisonEnd]="campaignOne.value.end">
<input matStartDate placeholder="Start date" formControlName="start">
<input matEndDate placeholder="End date" formControlName="end">
</mat-date-range-input>
<mat-datepicker-toggle matSuffix [for]="campaignTwoPicker"></mat-datepicker-toggle>
<mat-date-range-picker #campaignTwoPicker></mat-date-range-picker>
</mat-form-field>

再度実行すると、以下のように2つの日付範囲ピッカーに設定された日付を、比較して表示できます。

この他にも、フォームの色を変更できるようにして視認性を高めたり、日付のバリデーションを追加したりすることも可能です。

また、スマートフォンでのユーザビリティへの対応もできるようになっています。これはTouch UI modeと呼ばれる仕組みで、カレンダー部分をタップすると大きなカレンダーが表示され、日付を選択しやすくなるものです。PCだけでなく、スマートフォンのユーザーに対しても対応しやすくなっているのはありがたいポイントの一つだと言えるでしょう。

公式サイトでは、日付範囲ピッカーを含めた各種機能の使い方を、サンプルコードやStaclBlitz上で動かせるサンプルなどで確認することができるので、こちらもご覧ください。

グレープシティのUIコンポーネントの日付範囲ピッカーは?

グレープシティのJavaScriptUIコンポーネント「Wijmo(ウィジモ)」でも、近々新しいコントロールとして、日付範囲ピッカーを追加する計画があります。

新しいコントロール

  • 日付範囲入力
    開始日時と終了日時を選択します。

こちらも他のコントロール同様、日本の業務システムで使いやすいコントロールとなるよう日々開発を進めておりますので、ご期待いただければと思います。

Wijmoの日付入力をはじめとした各種コントロールはこちらのデモサイトからお試しできます。