JavaScript オンリーで動的に form タグを作ってデータを送信する方法

2 min read読了の目安(約2300字

はじめに

form で submit しないといけないけど送るデータが大量にあったり JavaScript で送るデータを管理していたりでわざわざ <input type='hidden' /> 追加するのもなぁーみたいな場面ってありませんか?

そんなときは JavaScript で完結する形で動的に Form タグを作ってデータを送信しましょう!

サンプルプログラム

すみません, 今回は良い感じの POST 先を用意できなかったのでボタンを押しても何も起きないです.
そのうちちゃんとサーバー立てて POST した内容を表示するページに差し替えておきますmm

https://runstant.com/phi/projects/38c483ff

コード

index.html
<button id='$btn'>submit</button>
main.js
window.onload = function() {
  // クリックイベントを登録
  $btn.onclick = (e) => {
    // form を動的に生成
    var form = document.createElement('form');
    form.action = '/hoge';
    form.method = 'POST';
    
    // body に追加
    document.body.append(form);
    
    // formdta イベントに関数を登録(submit する直前に発火)
    form.addEventListener('formdata', (e) => {
      var fd = e.formData;
      
      // データをセット
      fd.set('email', 'dummy@gmail.com');
      fd.set('password', '1234abcd');
    });

    // submit
    form.submit();
  };
};

解説

form データを動的に作ろう

シンプルに document.createElement() 関数で form タグを作るだけです.
作った後は action や method といった必要な情報をセットして bodyappend() します.

// form を動的に生成
var form = document.createElement('form');
form.action = '/hoge';
form.method = 'POST';

// body に追加
document.body.append(form);

formdata イベントでデータを登録しよう

form には submit する直前に発火する formdata というイベントがあります.
このイベントに登録した関数に渡ってくるイベントオブジェクトには form 要素に紐付いた FormData がぶら下がってくるので, このオブジェクトにデータをセットしたり追加することで form にデータを追加することができます.

// formdta イベントに関数を登録(submit する直前に発火)
form.addEventListener('formdata', (e) => {
  var fd = e.formData;
  
  // データをセット
  fd.set('email', 'dummy@gmail.com');
  fd.set('password', '1234abcd');
});

上記は HTML でいうところの

<form action='/hoge' method='POST'>
  <input type="hidden" name="email" value="dummy@gmail.com" />
  <input type="hidden" name="password" value="1234abcd" />
</form>

とほぼ同じ意味になります.

JavaScript で submit しよう

document に追加されている form 要素であれば submit() 関数を呼んであげるだけで submit されます!

// submit
form.submit();

これで formdata イベントが発火してデータがセットされた状態で送信されます.

おわりに

このように, HTML 前提の仕様に対しても頑張って JavaScript のみでアプローチすることでメンテナンスしやすくなったりコードがスッキリすることが多々あります.

最近は, Shopify の案件が増えてきて liquid でレガシーなフォームを作ることが多いんですが, やっぱり JavaScript 完結で作りたい気持ちが強くなってきたのでこの Tips を使って全部作り直したりしてます...

Shopify ってヘッドレスコマース謳ってる割には POST 前提だったり紐付けてるドメイン直下でアクション発火させないと購入ページいけなかったりで色々と辛いんですよね.

すみません愚痴でした...

form って意外と奥が深いので引き続き色々と Tips 発信していけたらと思います.