3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

formの中でのbuttonタグにつけたリンクが思ったような挙動をしてくれなかった時の対処と原因について

Posted at

この記事で書くこと

こんばんは。 :night_with_stars:
もう早いもので今年ももう少しになりました。師走ですね。

今回は、気を抜くと忘れてしまいそうな form 内で使用される button の挙動について残したいと思います。
アウトプットしてもう忘れないことが狙いです。

formの中で使われる buttonタグの挙動

よくある以下のようなインターフェイスを例にあげます。
formの中に書いてあるsubmitボタンと、それ以外のボタン。
(イメージしやすくするように、コードを書いているので、動作するコードでない可能性があります。ご了承ください。 :bow:

スクリーンショット 2019-12-05 18.59.06.png

「登録する」右側のボタンを押すと、フォームの内容がsubmitされます。後述する内容を意図して書いているかは横においておいて。
(今回バリデーションで弾かれて、というようなことは話したいことの外なので考慮していません。)

<!-- 何かサービス上で、登録する画面 -->
<form action="register_to_team" method="post">
  <button>登録する</button>
  <!-- もしくは以下のようにinputタグも一般的かと思います。 -->
  <input type="submit" value="登録する">
</form>

では、「マイページに戻る」が以下のようなコードだった場合、どうなるか、です。
両方とも、 /mypage.html に飛ばそうとしています。通常のリンクとして機能させたいようですね。((もちろん) Get です。)

<!-- 何かサービス上で、登録する画面 -->
<form action="register_to_team" method="post">
  <a href="/mypage.html">
    <button>マイページに戻る</button>
  </a>
  <!-- もしくは -->
  <button>
    <a href="/mypage.html">マイページに戻る</a>
  </button>
</form>

ただ、このボタンはどちらも期待した挙動( /mypage.html へのリンク )をしてくれません。
むしろ、「登録する」を押した挙動になってしまいます。これは困った。思わぬバグを生んでしまいます。

でも、何故でしょうか? :thinking:

buttonタグ

HTML5タグリファレンス をきちんと確認します。

type属性はボタンの種類を指定する際に使用します。 type属性の値には、以下の3種類のいずれかを指定することができます。 初期値はtype="submit"です。
type="submit" …… フォーム入力内容を送信するサブミットボタン(初期値)
type="reset" …… フォーム入力内容をリセットするリセットボタン
type="button" …… 何もしない汎用的な押しボタン
form属性は、どのフォームと関連付けるかを指定する際に使用します。 は初期値では直近の親要素となると関連付けられますが、 のid属性の値とのform属性の値を一致させることで、 ボタンを特定のフォームと関連付けることができます。 ボタンを任意の場所に配置できるので、ウェブアプリケーションなどを制作する際には便利かもしれません。

以下の2箇所に注目です。

初期値はtype="submit"です。

buttonは初期値では直近の親要素となる

と関連付けられます

なるほど。

今回「マイページに戻る」のボタンを想定して書かれているコードは、type属性をbuttonに指定していません。
つまり type="submit" ということですね。
初期値をあえて入れた状態で見てみます。
特に、idなども設定しておらず、親要素となる <form> と紐付けられるわけですから、書いた通りの、親要素のaction先である、 register_to_team にsubmitしてしまっていた、ということです。

以下のいづれかも、正常に、 /mypage.html へリンクすることができるかと思います。

<!-- 何かサービス上で、登録する画面 -->
<form action="register_to_team" method="post">
  <a href="/mypage.html">
    <button type="button">マイページに戻る</button>
  </a>
  <!-- もしくはちょっとクリックする箇所が狭いですが、今度は一応動きますよ。 -->
  <button type="button">
    <a href="/mypage.html">マイページに戻る</a>
  </button>
  <!-- もしくはbuttonタグに拘らずに、divなどのタグを使用する。 -->
  <a href="/mypage.html">
    <div class="button_style">マイページに戻る</div>
  </a>
</form>

ここまで来ると、「会員登録」のボタンがどちらも、submitされるのはきちんと理解できる準備が整いました。

<!-- 何かサービス上で、登録する画面 -->
<form action="register_to_team" method="post">
  <button>登録する</button>
  <!-- もしくは以下のようにinputタグも一般的かと思います。 -->
  <input type="submit" value="登録する">
</form>

これは以下のように解釈されていました。ですから、buttonでも確かにsubmitされていた、というわけです。

<!-- 何かサービス上で、登録する画面 -->
<form action="register_to_team" method="post">
  <button type="submit">登録する</button>
  <!-- もしくは以下のようにinputタグも一般的かと思います。 -->
  <input type="submit" value="登録する">
</form>

忘れてしまいがちですが、特に他の人が書いたコードであっても、formの中で使われる <button> には注意したいです。

buttonタグのformaction属性について

この属性を知らなかったので、ついでに調べてみました。

caniuse.com
HTML5タグリファレンス

formaction属性(送信先URL)・ formenctype属性(送信するデータの形式)・ formmethod属性(送信方法)・ formnovalidate属性(入力されたデータの妥当性を確認しない)・ formtarget属性(フォーム送信するターゲット先)は、

の属性でも同様の指定をすることができますが、 側でこれらの属性を指定すると、の指定より優先されます。

formaction属性・formenctype属性・formmethod属性・formnovalidate属性・formtarget属性は、 type="submit"の場合にのみ指定することができます。

どうやら、 <button> に設定すると、formに設定された内容を上書きすることができるようです。ボタン毎に、submit先が異なる場合は、有効そうです。
今回は、ただ単にlinkさせたいだけなので <a>タグ で対応しましたが、以下のようにも書ける、ということですね。

<!-- 何かサービス上で、登録する画面 -->
<form action="register_to_team" method="post">
  <button formaction="mypage.html" formmethod="get">マイページに戻る</button>
</form>

最後に

悩んだ時は、ドキュメントに戻る、というのを大事にしていて良かった。
もし間違ってる点や、より良い解決方法などありましたら、コメントいただければ幸いです。 :bow:
それでは。 :door:

3
1
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
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?