📅

showPickerを使ってフィールドのどこをクリックしても日付Pickerが開くようにする

2024/12/17に公開

はじめに

この記事ではHTML5の<input type="date">を拡張して、本来はカレンダーアイコンをクリックすることでしか開けない日付Picker(date picker)を、フィールドのどこをクリックしても開くようにする方法を紹介します。

https://developer.mozilla.org/ja/docs/Web/HTML/Element/input/date

showPicker()を使用する

HTMLInputElement.showPicker()は、実行するとinput要素のブラウザのPickerを表示することができます。

今回はshowPickerメソッドを使用してonClickイベント時にshowPickerを呼び出し、クリックイベントから日付Pickerを直接表示するようにします。そうすることで入力欄全体をPickerのトリガーにすることができます。

https://developer.mozilla.org/ja/docs/Web/API/HTMLInputElement/showPicker

実装コード

私が実装した主な環境は以下の通りです。

  • React(v17.0.2)
  • TypeScript(v4.3.5)
  • styled-components(v6.0.5)

必要なモジュールのインポート

Reactを使用するための基本モジュールをインポートしています。ForwardedRefとforwardRefは親コンポーネントから子コンポーネントにrefを渡すことができ、フォームの制御やDOM操作に使用しています。

calendar.tsx
import React, { ForwardedRef, forwardRef } from 'react';
import styled from 'styled-components';

型定義

defaultValueには任意で日付フィールドの初期値を指定するためにstringで定義をしていて、onChangeは任意で日付が変更されたときに呼び出されるコールバック関数を型React.ChangeEvent<HTMLInputElement> で定義しています。

calendar.tsx
type CalendarProps = {
  defaultValue?: string;
  onChange?: (event: React.ChangeEvent<HTMLInputElement>) => void;
};

Propsの受け取り

forwardRefを使用してrefを渡すことでこのコンポーネントを使用する親コンポーネントから直接input要素への参照を取得できます。

calendar.tsx
const Calendar = forwardRef((
  { defaultValue, onChange }: CalendarProps,
  ref: ForwardedRef<HTMLInputElement>
): JSX.Element => {

handleClickの処理

後述のinputタグがクリックされたときにhandleClickを呼び出します。型アサーションを使って、currentTarget が HTMLInputElement であり、showPicker メソッドを持つことを明示しています。

calendar.tsx
const handleClick = (event: React.MouseEvent<HTMLInputElement>) => {
  (event.currentTarget as HTMLInputElement & { showPicker: () => void }).showPicker();
};

return内の構造

inputタグに処理に必要なプロパティ、属性を追加しています。onClickプロパティでhandleClickをバインドしてクリック時に日付Pickerを表示するようにしています。

calendar.tsx
return (
  <StyledCalendar>
    <img src={任意のカレンダーアイコンのパス} alt="カレンダーアイコン" />
    <input
      ref={ref}
      type="date"
      defaultValue={defaultValue}
      onChange={onChange}
      onClick={handleClick}
    />
  </StyledCalendar>
);

全体のコード

全体のコードはこちら
calendar.tsx
import React, { ForwardedRef, forwardRef } from 'react';
import styled from 'styled-components';

type CalendarProps = {
  defaultValue?: string;
  onChange?: (event: React.ChangeEvent<HTMLInputElement>) => void;
};

const StyledCalendar = styled.div`
  // スタイルは省略
`;

const Calendar = forwardRef((
  { defaultValue, onChange }: CalendarProps,
  ref: ForwardedRef<HTMLInputElement>
): JSX.Element => {
  const handleClick = (event: React.MouseEvent<HTMLInputElement>) => {
    (event.currentTarget as HTMLInputElement & { showPicker: () => void }).showPicker();
  };

  return (
    <StyledCalendar>
      <img src={任意のカレンダーアイコンのパス} alt="カレンダーアイコン" />
      <input
        ref={ref}
        type="date"
        defaultValue={defaultValue}
        onChange={onChange}
        onClick={handleClick}
      />
    </StyledCalendar>
  );
});

export default Calendar;

終わりに

この記事では、HTML5 の showPicker を活用して、入力欄全体をクリックして日付ピッカーを開く方法を紹介しました。
日付Picker(date picker)を入力欄全体にバインドされることでユーザー体験も良くなると思います。もしライブラリ等を使用せずに日付Pickerを実装する時には参考にしてみてください。

実際に就活会議上で以下のように動作しています。

ポート株式会社 エンジニアブログ

Discussion