JavaScript の formdata イベントのまとめ
JavaScript (以下 JS )の formdata
イベントについて簡単にまとめました。
formdata
イベントとは
formdata
イベントは HTML のフォーム( <form>
)の送信処理の直前に発火するイベントです。
従来の submit
イベントよりも後のタイミングで発火します。
セットされたイベントハンドラは同期的にディスパッチされるため( dispatched synchronously )、サーバーへの通信はイベントハンドラの処理が完了した後に行われます。
Google Chrome にはバージョン 77 ( 2019 年 9 月リリース)で導入されました。 Chrome 以外のブラウザにいつ頃導入されるのかというのは記事執筆時点ではわかっていません。
formdata
イベントを含む一連の処理の正確な流れについては次のページが参考になります:
以下使い方について。
formdata
イベントの使い方
formdata
イベントでは、イベントハンドラに引数として渡される Event
オブジェクトに formData
というプロパティがセットされています。
formData
の中身は、対象のフォームのデータを一式格納した FormData
オブジェクトです。
form.addEventListener('formdata', event => {
// フォームの FormData オブジェクトにアクセスできる
console.log(event.formData);
// キーを確認する
console.log(Array.from(event.formData.keys()));
// バリューを確認する
console.log(Array.from(event.formData.values()));
// キー・バリューのペアを確認する
console.log(Array.from(event.formData.entries()));
});
この event.formData
を使うことで、フォームデータがサーバーに送信される直前のタイミングでデータの追加・変更・削除がかんたんに行えます。
form.addEventListener('formdata', event => {
// キー・バリューを追加する
// キーがすでに存在する場合は同じキーで値を追加する
event.formData.append('key', 'value');
// 特定のキーの値をセットする
// キーがすでに存在する場合は上書き、存在しない場合は追加する
event.formData.set('key', 'value');
// 特定のキーのエントリーを削除する
event.formData.delete('key');
});
FormData
オブジェクトの詳細のインタフェースについては Mozilla のページにわかりやすく説明されているので興味がある方はそちらのページを見てみてください。
記事作成時点で FormData
が持つメソッド一覧は次のとおりとなっています:
FormData.append()
FormData.delete()
FormData.entries()
FormData.get()
FormData.getAll()
FormData.has()
FormData.keys()
FormData.set()
FormData.values()
formdata
イベントのメリットは、フォーム送信時の送信データへのアクセスと追加・変更・削除がかんたんにできることです。
(私が理解しているかぎり)従来からある submit
イベントを使っても同様のことはできたのですが、その方法が回りくどくあまり直感的ではありませんでした。
具体的には、 submit
イベントのイベントハンドラからはフォームの FormData
オブジェクトにアクセスすることができないため、データを追加したいときは「フォームに hidden input 要素を追加する」、データを変更したいときは「フォームの elements
プロパティの奥の方で変更を加える」、という間接的なアプローチを採る必要がありました。
要は、フォームのデータをちょろっといじりたいだけでも DOM を操作する必要がありました。
submit
を使った場合のフォーム送信データの追加や変更のイメージは次のとおりです:
form.addEventListener('submit', event => {
// hidden input をフォームに追加することでデータを追加する
let input = document.createElement('input');
input.setAttribute('type', 'hidden');
input.setAttribute('name', 'new key');
input.setAttribute('value', 'new value');
event.target.appendChild(input);
// フォームの elements の中身を変更することでデータを変更する
for (let element of event.target.elements) {
if (element.name === 'target') {
element.value += ' extra suffix';
}
}
});
ちなみに、 formdata
イベントはキャンセル不可とのことで、イベントハンドラで event.preventDefault()
を呼んでもフォームの送信のキャンセルはできません。
バリデーションをかけ条件によってはデータ送信をキャンセルしたいような場合には従来の submit
イベントを使うことになります。
以上です。
コメント
個人的な経験では、フォームを使わず JS 側だけで通信を行う完全な Single Page Application ではなくて、ひとつのページの中でフォームと Vue.js 等のフレームワークを両方使うような場合には、この「フォーム送信時にデータを追加・変更する」という処理をしたくなることが結構ある気がします。
記事作成時点では formdata
イベントが登場して間もない & Chrome 以外ではまだ使えないため実プロジェクトで使ったことはありませんが、フォームの送信データを DOM を介さず直接変更できるというのはとても便利なので今後 formata
イベントの利用頻度が増えてくることと思います。