この記事で書くこと
こんばんは。
もう早いもので今年ももう少しになりました。師走ですね。
今回は、気を抜くと忘れてしまいそうな form
内で使用される button
の挙動について残したいと思います。
アウトプットしてもう忘れないことが狙いです。
formの中で使われる buttonタグの挙動
よくある以下のようなインターフェイスを例にあげます。
formの中に書いてあるsubmitボタンと、それ以外のボタン。
(イメージしやすくするように、コードを書いているので、動作するコードでない可能性があります。ご了承ください。 )
「登録する」右側のボタンを押すと、フォームの内容が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
へのリンク )をしてくれません。
むしろ、「登録する」を押した挙動になってしまいます。これは困った。思わぬバグを生んでしまいます。
でも、何故でしょうか?
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属性について
この属性を知らなかったので、ついでに調べてみました。
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>
最後に
悩んだ時は、ドキュメントに戻る、というのを大事にしていて良かった。
もし間違ってる点や、より良い解決方法などありましたら、コメントいただければ幸いです。
それでは。