🎂

MUIのDatePickerで誕生日を可能な限り入力しやすくする

に公開
2

はじめに

誕生日が入力しやすいフォームを作成するのは意外と大変です。一方で実装はなるべくサボりたかったので、MUIのDatePickerのオプションを調べていたところ、ほとんど手を加えることなく実装できてしまいました。今回はそのちょっとしたノウハウを紹介します。

完成形

import { AdapterDateFns } from "@mui/x-date-pickers/AdapterDateFns";
import { DatePicker } from "@mui/x-date-pickers/DatePicker";
import { LocalizationProvider } from "@mui/x-date-pickers/LocalizationProvider";
import ja from "date-fns/locale/ja";

<LocalizationProvider
  dateAdapter={AdapterDateFns}
  adapterLocale={ja}
  localeText={{
    previousMonth: "前月",
      nextMonth: "次月"
  }}
>
  <DatePicker
    label="誕生日"
    format="yyyy年MM月dd日"
    openTo="year"
    views={["year", "month", "day"]}
    maxDate={new Date()}
    value={value}
    onOpen={() => {
      if (value === null) {
        setValue(new Date(1990, 0, 1));
      }
    }}
    onChange={(newValue) => {
      setValue(newValue);
    }}
  />
</LocalizationProvider>

デモ: https://codesandbox.io/s/birthdaypicker-demo-3sdekh?file=/demo.tsx

CodeSandboxのデモですが、初回読み込みでdate-fns/locale/jaのインポートができないなどのエラーが発生することがあります。その際は一行編集して保存するなどで回避できます。

やったこと

YearPickerを最初に表示する

DatePickerには年を選択するYearPickerが用意されていますが、デフォルト設定では日を選択するCalendarPickerが表示されてしまいます。
これを回避するには、openTo="year" を指定して、YearPickerを真っ先に開くよう指定します。

MonthPickerを表示する

MUIには月を選択するMonthPickerが用意されていますが、デフォルト設定では表示されず、カレンダー表示にある左右の矢印を連打しないといけません。
これを回避するには、views={["year", "month", "day"]} のオプションを指定して、MonthPickerも表示するように指定します。これだけで十分実用的です。

未来の日付を非表示にする

maxDate={new Date()}で非表示にできます。 disableFuture={true}は選択できなくなるだけで表示はされます。

ローカライズする

LocalizationProviderでローカライズできます。LocalizationProviderのlocaleTextオプションを指定することで、ariaラベルもローカライズできます。

また、mask="____年__月__日"inputFormat="yyyy年MM月dd日" format="yyyy年MM月dd日"を指定することで、入力結果の表示もローカライズできます。キーボード入力の際も、数字を入力するだけで「年月日」を補完してくれます。

最初に表示する年を指定する

例えば1990年付近の生まれの利用者が多い場合、YearPickerを開いたときに1990年が指定されていてほしいです。これは、愚直ではありますが、onOpenに初期値を設定する関数を渡すことで実現できます。

onOpen={() => {
  if (value === null) {
    setValue(new Date(1990, 0, 1));
  }
}}

うまくいかなかったこと

今日の日付のハイライトを無効化する

disableHighlightToday={true}で今日の日付のハイライトが無効化できるらしいのですが、うまくいきませんでした。というのも、年を選択した段階で、月と日に今日の日付が自動選択されるため、結果として今日の日付がハイライトされるためです。また、年が1900年から表示されるため、なかなかにお年寄り向けのDatePickerになってしまいます。なにかいい方法あれば教えて下さい。

2024/12/06
MUIのアップデートで年を選択した段階で1月1日が自動選択されるように変更されています。またdisableHighlightToday={true}は今日の日付に白丸をつけるのを無効化する機能で、自動選択を回避するものではありませんでした。

参考

MUI DatePicker API Reference: https://mui.com/x/api/date-pickers/date-picker/

Discussion

nap5nap5

素朴にテキストフィールドでチャレンジしてみました

Nakano as a ServiceNakano as a Service

確かに素朴に実装してしまうのもいいですね、コード例が充実してとてもありがたいです!