0
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?

Ant Design の DatePicker をカスタムして、フォーカスアウトで指定したフォーマットに変換する方法

Posted at

はじめに

Ant Design は、React用の UIフレームワークの一つで、洗練されたデザインと豊富なコンポーネントが特徴だが、あまり日本語の記事がない。
その中でも DatePicker は、日付を選択するためのコンポーネントになる。
ラップしたカスタム部品を作成する機会があったのでメモ書きとして残しておく。

Ant Design の DatePicker とは?

DatePicker は、カレンダー UI を提供し、ユーザーが日付を選択できるようにするコンポーネントで以下のように簡単に導入できる。

import React, { useState } from 'react';
import { DatePicker } from 'antd';
import dayjs, { Dayjs } from 'dayjs';

const BasicDatePicker: React.FC = () => {
  const [date, setDate] = useState<Dayjs | null>(null);

  return <DatePicker value={date} onChange={setDate} format="YYYY/MM/DD" />;
};

export default BasicDatePicker;

しかし、 YYYYMMDD 形式で入力された日付がフォーカスアウトされたタイミングで
YYYY/MM/DD 形式に変換する必要があり DatePicker をラップした CustomDatePicker 部品を作成した。

実装

CustomDatePicker の要件

  • YYYYMMDD の入力を受け付ける
  • ユーザーがフォーカスアウトした際にフォーマットを適用
  • デフォルトのフォーマットは YYYY/MM/DD
  • カレンダー選択時はそのまま反映
  • 無効な日付入力は null をセット

実装コード

以下のコードは CustomDatePicker の実装です。

import React from 'react';
import { DatePicker } from 'antd';
import dayjs, { Dayjs } from 'dayjs';

// DatePicker のプロパティを定義
export interface CustomDatePickerProps {
  value?: Dayjs | null; // 選択された日付(null 許容)
  onChange?: (date: Dayjs | null) => void; // 値の変更時に呼ばれるコールバック関数
  placeholder?: string; // プレースホルダー
  format?: string; // 日付のフォーマット
  disabled?: boolean; // 無効化フラグ
}

// Ant Design の DatePicker をカスタマイズしたコンポーネント
const CustomDatePicker: React.FC<CustomDatePickerProps> = ({
  value,
  onChange,
  placeholder = '日付の入力・選択をしてください', // デフォルトのプレースホルダー
  format = 'YYYY/MM/DD', // デフォルトのフォーマット
  disabled = false, // デフォルトで有効
}) => {
  
  // カレンダーで日付を選択したときに実行
  const handleChange = (date: Dayjs | null) => {
    onChange?.(date); // 選択した日付を親コンポーネントに渡す
  };

  // フォーカスアウト時に入力値を検証・変換する処理
  const handleBlur = (e: React.FocusEvent<HTMLElement>) => {
    if (!(e.target instanceof HTMLInputElement)) return; // 入力フィールドでない場合は処理しない
    if (!onChange) return; // onChange が渡されていない場合は処理しない

    const inputValue = e.target.value.trim(); // ユーザー入力を取得し、前後の空白を削除

    // YYYYMMDD(例: 20240131)形式で入力された場合
    if (/^\d{8}$/.test(inputValue)) {
      const formattedDate = dayjs(inputValue, 'YYYYMMDD').format(format); // 指定フォーマットへ変換
      onChange(dayjs(formattedDate, format));
    } 
    // ユーザーが指定フォーマット (YYYY/MM/DD など) で入力した場合
    else if (dayjs(inputValue, format, true).isValid()) {
      onChange(dayjs(inputValue, format));
    } 
    // 無効な日付の場合
    else {
      onChange(null); // 無効な値は null を設定
    }
  };

  return (
    <DatePicker
      value={value} // 選択された日付
      format={format} // フォーマットを適用
      inputReadOnly={false} // 手動入力を許可
      placeholder={placeholder} // プレースホルダーの表示
      onBlur={handleBlur} // フォーカスアウト時の処理
      onChange={handleChange} // 日付選択時の処理
      disabled={disabled} // 無効化の設定
    />
  );
};

export default CustomDatePicker;

CustomDatePicker の動作確認

  1. YYYYMMDD 形式で入力すると、自動で YYYY/MM/DD にフォーマットされる
  2. 無効な日付を入力すると null になる(画面上は非表示)
  3. DatePicker のカレンダー UI から選択すると、そのまま値がセットされる

理想は、Ant Design の仕様をそのまま利用する要件にすることがいいと思うのですが、
そうもいかないのがシステム開発・・・

0
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
0
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?