1つのフォーム内で複数の送信ボタンを扱う

はじめに

この記事はアソビュー! Advent Calendar 2024 の13日目(裏面)です。

こんにちは、アソビューでフロントエンドエンジニアをしている村井です。皆さんは、1つのフォームの中で2つの送信ボタンを扱ったことはありますか?

複数の送信ボタン配置時に押されたボタンを判別したい

私が担当する開発において、同じ入力項目を使って「検索」と「CSVダウンロード」の2つの機能を実装することで、ユーザーが手間なく必要な情報を取得できるようにする必要がありました。

しかし、1つのフォームに複数の送信ボタンを配置すると、どのボタンが押下されたのかを判別する必要があります。 ボタンの区別ができなければ、適切な処理を実行することができず、ユーザーに混乱を招く可能性があります。

本記事では、この課題をどのように解決したのか、実装時のポイントを交えながらご紹介していきたいと思います。

解決策

JavaScriptのsubmitterプロパティを活用することで、押下された送信ボタンを特定する方法を見つけました。submitterプロパティは、フォームの送信イベント(SubmitEvent)から取得でき、押下したボタン要素の情報を取得することができます。この特性を活用することで、フォーム内の複数の送信ボタンを区別して処理することができます。

developer.mozilla.org

実装の詳細

では、具体的にどのように実装するのか、実際のコードを示しながら説明していきます。 以下が実際の実装コードです。フォームの管理にはreact-hook-formを使用しています。

type FieldValue = {
  keyword: string;
};

type RequestType = 'search' | 'download';

export const SearchForm = () => {
  const { register, handleSubmit } = useForm<FieldValue>();

  return (
    <form
      onSubmit={handleSubmit(async (data, event) => {
        const nativeEvent = event?.nativeEvent as SubmitEvent;
        const submitter = nativeEvent.submitter;
        const requestType = submitter?.id || ('search' as RequestType);
        if (requestType === 'download') {
          await download(data);
        } else {
          await search(data);
        }
      })}
    >
      <input type="text" {...register('keyword')} />
      <button type="submit" id="search">
        検索
      </button>
      <button type="submit" id="download">
        CSVダウンロード
      </button>
    </form>
  );
};

各送信ボタンに id 属性(searchdownload)を設定し、handleSubmit 関数内で event.nativeEvent.submitter.id を使用することで、フォーム送信時にどのボタンが押下されたかを特定しています。取得した type(ボタンの id)に応じて、onPreSubmit 関数内で処理を分岐させ、requestTypesearch の場合は検索処理を、download の場合は CSV ダウンロード処理を実行します。

まとめ

submitterプロパティを活用することで、1つのフォーム内で複数の送信ボタンを効果的に扱うことができました。この実装により、ユーザーは同じ入力データを使って「検索」や「CSV ダウンロード」といった異なる操作をスムーズに行うことができ、UXの向上につながりました。

We're hiring!

アソビューでは、より良いプロダクトを世の中に届けるため、共に挑戦していただけるエンジニアを募集しています。カジュアル面談も実施していますので、興味を持たれた方はぜひエントリーをお願いいたします!

www.asoview.com

speakerdeck.com

技術情報を発信する公式アカウントもございます。ぜひフォローをお願いします! https://twitter.com/Asoview_dev