🎉

Material-UIのDate Pickerをカスタマイズしよう

2021/09/01に公開

はじめに

Material-UIのDate Pickerって見た目もシンプルでかなりいい感じですよね~

デフォルトのDate Picker
しかし、やはりデフォルで使用するには表示が日本人向けではない...
英語というだけでかなりの拒否反応を起こしてしまう方もいたりいなかったりしますよね。
ここはしっかりと日本人向けにカスタマイズしていこうじゃないかという趣旨の記事となっております。

基本の使い方

ここはドキュメントをサラッと読むだけでも分かる部分なので読み飛ばしていただいても OK

インストール

Date Pickerですがcoreパッケージではなく「Material-UI Picker」という別パッケージになっています。
そのため、まずはこちらのパッケージをインストールしましょう。
日時管理ライブラリには今回は「date-fns」を利用します。
(このdate-fnsは日時処理にめちゃくちゃ便利なのでおすすめです)

# pickerパッケージ
npm i @material-ui/pickers

# pickerが利用する日時管理ライブラリも併せてインストール
npm i @date-io/date-fns@1.x date-fns

設置

早速Date Pickerコンポーネントを設置してみましょう。

import DateFnsUtils from '@date-io/date-fns'
import { DatePicker, MuiPickersUtilsProvider } from '@material-ui/pickers'

const App = () => {
  const [date, setDate] = useState<Date | null>(new Date())

  const changeDateHandler = (newDate: Date | null): void => {
    setDate(newDate)
  }

  return (
    <MuiPickersUtilsProvider utils={DateFnsUtils}>
      <DatePicker value={date} onChange={changeDateHandler} />
    </MuiPickersUtilsProvider>
  )
}

設置するだけならこれで完了です。

左: 設置されるコンポーネント 右: ダイアログ

カスタマイズ開始

1. 選択されている日付のフォーマット

選択されている日付がテキストフィールドのようなコンポーネントに表示されますが、まずはこちらを日本語表記に修正します。

 <MuiPickersUtilsProvider utils={DateFnsUtils}>
    <DatePicker
      value={date}
+     format="yyyy年M月d日"
      onChange={changeDateHandler}
    />
 </MuiPickersUtilsProvider>


左: befor 右: after

2. ダイアログの日本語表記

ダイアログの月や曜日が英語表記になっています。
こちらを日本語表記に修正します。これは簡単にできます。

+ // date-fnsから日本localeをimport
+ import jaLocale from 'date-fns/locale/ja'

  // Providerに渡すだけ
  <MuiPickersUtilsProvider
    utils={DateFnsUtils}
+   locale={jaLocale}
  >
    <DatePicker value={date} format="yyyy年M月d日" onChange={changeDateHandler} />
  </MuiPickersUtilsProvider>


惜しい!
英語表記ではなくなりましたが、表記順が海外仕様のままなので違和感のあるものとなってしまっています。

3. ヘッダ部の表記

2で日本語表記にはなりましたが、一般的な表記順ではないので見慣れた形に修正します。
このあたりから若干ですが難易度が上がってきます。
ヘッダ部分の情報はすべてProviderのutilsに渡しているDateFnsUtilsが担っています。
そのため、DateFnsUtilsを継承した自作Utilsを用意して渡すようにするというのが方針となります。
getDatePickerHeaderTextがダイアログヘッダ部のテキストを取得するメソッドなので、こちらを実装します。

+ import { format } from 'date-fns'

 // 自作Utils
+ class JaLocalizedUtils extends DateFnsUtils {
+   // ヘッダ部分のテキストを取得するメソッド
+   getDatePickerHeaderText(date: Date) {
+     return format(date, 'M月d日(E)', { locale: this.locale })
+   }
+ }

 <MuiPickersUtilsProvider
-  utils={DateFnsUtils}
+  utils={JaLocalizedUtils}
   locale={jaLocale}
 >
   <DatePicker value={date} format="yyyy年M月d日" onChange={changeDateHandler} />
 </MuiPickersUtilsProvider>

できましたね!
formatの第二引数に渡している文字列で表記をカスタマイズできるので、皆様のお好みの表記に変更してみてください。
format関数について

4. カレンダー部の年月表記

ヘッダ部は3で良くなりましたが、カレンダー部の年月表記がまだ順序がよろしくないので見慣れた形に修正します。
こちらも同様に自作Utilsの中にgetCalendarHeaderTextを実装します。

 // 自作Utils
  class JaLocalizedUtils extends DateFnsUtils {
+   // カレンダーのヘッダ部分のテキストを取得するメソッド
+   getCalendarHeaderText(date: Date) {
+     return format(date, 'yyyy年M月', { locale: this.locale })
+   }

    // ヘッダ部分のテキストを取得するメソッド
    getDatePickerHeaderText(date: Date) {
      return format(date, 'M月d日(E)', { locale: this.locale })
    }
  }

 <MuiPickersUtilsProvider
   utils={JaLocalizedUtils}
   locale={jaLocale}
 >
   <DatePicker value={date} format="yyyy年M月d日" onChange={changeDateHandler} />
 </MuiPickersUtilsProvider>

できましたね!
これで英語に拒絶反応が出てしまう方々にも心置きなく使ってもらえるDate Pickerになったのではないでしょうか。

おまけ

デフォルトだと年の選択には西暦が用いられています。

年のリストは西暦表示

システム屋としては和暦はあまり使いたくないですが、表示上は和暦にしてほしいなんて要望もあるかもしれません。
これを和暦表示に変更してみましょう。
この年リストのテキストはgetYearTextにて設定することができます。

  // 自作Utils
  class JaLocalizedUtils extends DateFnsUtils {
    // カレンダーのヘッダ部分のテキストを取得するメソッド
    getCalendarHeaderText(date: Date) {
      return format(date, 'yyyy年M月', { locale: this.locale })
    }

    // ヘッダ部分のテキストを取得するメソッド
    getDatePickerHeaderText(date: Date) {
      return format(date, 'M月d日(E)', { locale: this.locale })
    }

+   // 年リストのテキストを取得するメソッド
+   getYearText = (date: Date): string => {
+     let wareki = ''
+     const seireki = date.getFullYear()
+
+     if (seireki < 1926) {
+       wareki = `大正${String(seireki - 1911)}`
+     } else if (seireki === 1926) {
+       wareki = '大正15年, 昭和1年'
+     } else if (seireki < 1989) {
+       wareki = `昭和${String(seireki - 1925)}`
+     } else if (seireki === 1989) {
+       wareki = '昭和64年, 平成1年'
+     } else if (seireki < 2019) {
+       wareki = `平成${String(seireki - 1988)}`
+     } else if (seireki === 2019) {
+       wareki = '平成31年, 令和1年'
+     } else {
+       wareki = `令和${String(seireki - 2018)}`
+     }
+
+     return wareki
+   }
  }

 <MuiPickersUtilsProvider
   utils={JaLocalizedUtils}
   locale={jaLocale}
 >
   <DatePicker value={date} format="yyyy年M月d日" onChange={changeDateHandler} />
 </MuiPickersUtilsProvider>


和暦表示

なんとも不格好な処理内容になっていますが目的は達成できましたね。
ちなみに、ダイアログヘッダ上部の年表示もこちらにつられて変更されています。

おわりに

Material-UIのDate Pickerは見た目もよくてとても使いやすいコンポーネントですが、日本語表記にするために若干の手間がかかってしまうのでまとめてご紹介しました。
表記以外にも様々な設定が可能なので、ぜひ自身のプロジェクトに合ったDate Pickerにカスタマイズしてみてください!

Discussion