9.

buttonでformをsubmitさせない方法|type=button・preventDefault

編集
この記事の要点
  • <form> の中に置いた <button> の既定 type は submit。何もしないボタンには必ず type="button" を指定する
  • JavaScript 側で止めるなら event.preventDefault() をクリックハンドラ先頭で呼ぶ
  • Enter キーでの暗黙送信を防ぐなら form 全体の submit イベントpreventDefault
  • ボタンをform の外に置く、または form="別 form の id" で関連先を切り替える方法もある
  • アクセシビリティ: 単なる装飾なら <div> ではなく <button type="button">。キーボード操作とフォーカスが標準でついてくる

結論: type="button" を明示する

<form> の内側にある <button> は、type を省略すると submit 扱いになります。クリックや Enter キーで意図せずフォームが送信され、ページがリロードされたり API が叩かれたりします。これを防ぐ最も簡単な方法は、ボタン側に type="button" を書くことです。

<form action="/save" method="post">
  <input type="text" name="title">

  <!-- 送信しない補助ボタン -->
  <button type="button" onclick="addRow()">行を追加</button>

  <!-- 送信ボタン -->
  <button type="submit">保存</button>
</form>

button 要素の type 一覧

type動作
submit(既定)所属する form を送信
button何もしない(JS から制御)
resetform を初期値に戻す

JavaScript で止める

既存コードで type を書き換えられない、または条件によって送信したいときは preventDefault() を使います。

// クリック時に止める
document.querySelector('#myBtn').addEventListener('click', e => {
  e.preventDefault();    // submit 動作キャンセル
  // ここで自前処理
  doSomething();
});

// onclick 属性内なら return false でも止まる(古典)
// <button onclick="doSomething(); return false;">押す</button>

Enter キー暗黙送信を止める

type="button" でも、フォーム内のテキスト入力でEnter キーを押すと、フォーム内で最初に見つかった type="submit" ボタン(もしくはデフォルト挙動)で送信されます。送信を全面禁止したい場合は、form の submit イベント自体を止めます。

const form = document.querySelector('#searchForm');
form.addEventListener('submit', e => {
  e.preventDefault();      // どんな経路でも送信させない
  // ここで Ajax / 自前処理
  fetchResults(form.elements.q.value);
});

あるいはテキスト入力の Enter キーを個別に止める方法もあります。

input.addEventListener('keydown', e => {
  if (e.key === 'Enter') {
    e.preventDefault();
  }
});

form の外にボタンを出す / 関連付け替え

レイアウト上どうしても form の中に置きたいが、送信対象にしたくないケースでは、HTML5 の form 属性で所属を切り替えることもできます。

<!-- 別 form と関連付け -->
<form id="formA" action="/a"></form>
<form id="formB" action="/b"></form>

<!-- 物理的には formA の中だが、押すと formB が送信される -->
<form id="formA">
  <input name="x">
  <button type="submit" form="formB">B を送る</button>
</form>

2 つ以上の送信ボタンを使い分ける

「下書き保存」「公開」のように同じ form で複数の送信先を持ちたいときは、formaction / formmethod 属性で個別に上書きできます。

<form action="/save" method="post">
  <input name="title">

  <button type="submit">保存</button>
  <button type="submit" formaction="/publish">公開</button>
  <button type="button" onclick="preview()">プレビュー</button>
</form>

アクセシビリティ上の補足

「クリックできる装飾」を作りたいときに <div onclick><span> を使うのは避け、<button type="button"> を選んでください。Tab フォーカス、Space / Enter での起動、スクリーンリーダの「ボタン」アナウンスがすべて標準で備わります。CSS で見た目を調整すればよいだけです。

関連

  • HTML — マークアップ言語
  • input要素 — 同じくフォーム部品
  • button要素 — 本記事の対象
  • form要素 — 親フォーム
  • preventDefault — ブラウザ既定動作の抑止
編集
Post Share
子ページ

子ページはありません

同階層のページ
  1. 環境構築
  2. 文法
  3. 要素一覧
  4. API
  5. テンプレートエンジン
  6. <head>タグに書いた内容が<body>タグに移動する場合の解決方法
  7. 空白(スペース)の入力方法
  8. テキスト/セレクトボックス/ラジオボタン変更時のJS関数呼び出し
  9. buttonでformをsubmitさせない方法

最近更新/作成されたページ