フォーム送信を制御する
このレッスンで分かること
submitが起きるのはボタンではなくform要素ですevent.preventDefault()で、ブラウザの既定の動きを止められます
送信ボタンを押すと、打った文字が全部消える
お問い合わせフォームの送信ボタンを押してみてください。一瞬画面が白くなり、入力していた文字がすべて消えたはずです。エラーではありません。ブラウザが決められたとおりに動いた結果です。
form 要素には生まれつきの役割があります。中の入力内容をまとめてサーバーへ送り、返ってきた新しいページを表示する、という役割です。送り先を書かなければ自分自身のページに送るので、同じページが読み込み直されます。変数もイベントの登録も作り直しになり、前回書いた文字数の表示も、打った内容も、まとめて消えます。
インターネットの初期からある正しい仕組みです。ただ、いまのページで入力を調べたり、その場に結果を出したりしたいときには邪魔になります。送られる前に止めて、こちらで面倒を見たいのです。
止める相手はボタンではない
押されるのはボタンですが、イベントが起きるのは form です。ボタンの click で受けるやり方も一応は動きますが、すすめられません。フォームは入力欄で Enter キーを押しても送信されるからです。
| 受ける場所 | 拾えるもの | 抜けるもの |
|---|---|---|
| button の click | ボタンを押したとき | 入力欄での Enter 送信 |
| form の submit | 押したときも Enter のときも | なし |
登録する相手を取り違えると、エラーも出ないまま何も起きません。
JavaScript
// button では submit が起きないので、この処理は一度も呼ばれない
document.querySelector(".submit-button")
.addEventListener("submit", function (event) {
event.preventDefault();
});既定の動きを取り消すのが event.preventDefault() です。名前のとおり「既定の動きを、あらかじめ防ぐ」という意味で、event オブジェクトが持っています。前回まで「要らなければ書かなくてよい」と言っていた引数の event が、ここでは必須になります。
既定の動きを持つのは submit だけではありません。リンクの click はページを移動しますし、右クリックはブラウザのメニューを出します。どれも同じメソッドで止められます。
JavaScript
const helpLink = document.querySelector("#help-link");
helpLink.addEventListener("click", function (event) {
event.preventDefault(); // ページを移動させない
console.log("移動を止めて、その場で説明を出す");
});まず止める、それから考える
書く場所が大事です。処理の先頭近くに置いてください。途中でエラーが起きて preventDefault() の行まで届かないと、ページはそのまま送信されてしまいます。原因の分かりにくい不具合になるので、まず止める、それから考える、の順にします。
JavaScript
const surveyForm = document.querySelector(".survey-form");
surveyForm.addEventListener("submit", function (event) {
event.preventDefault(); // まず止める
// 止めたあとに、好きなだけ処理を書く
});止めるだけで終わると、押しても何も起きないページになります。見ている人は壊れていると思います。止めたら必ず、代わりの反応を返してください。メッセージを 1 行出す、ボタンの文字を変える、どれでもかまいません。押した手応えが返らない画面は、動いていないのと区別が付きません。
いま多くの Web サービスで、送信してもページが切り替わらないのは、どれもこの preventDefault() が土台にあるからです。ページが変わらないので、入力した内容も前の表示もそのまま残り、必要なところだけを書き換えられます。
return falseで止まると書かれた古い記事がありますが、あれはonsubmit属性の書き方の話です。addEventListenerで登録した関数の中では効きません。
よくある間違い
- 引数を受け取っていない —
function () {のままevent.preventDefault()を呼ぶとevent is not definedで止まり、止められないまま送信されます。丸かっこにeventと書き足します - メソッドの丸かっこを忘れる —
event.preventDefault;は関数を参照しただけで、呼んでいません。エラーも出ないので気付きにくく、ページだけが読み込み直されます
課題
- HTML の
.contact-formの中、送信ボタンのすぐ下にid="form-message"の空のpを足す - JavaScript で
.contact-formにsubmitイベントを登録する - 処理の引数に
eventを受け取り、いちばん先頭でevent.preventDefault()を呼ぶ - そのあと
#form-messageに「送信を受け付けました」と表示する