この内容は古いバージョンです。最新バージョンを表示するには、戻るボタンを押してください。
バージョン:4
ページ更新者:guest
更新日時:2026-06-11 07:10:02

タイトル: Javascript のみで form を post で submit する方法
SEOタイトル: JavaScript のみで form を POST 送信する方法完全ガイド

この記事の要点
  • HTML を一切書かず、JavaScript だけで <form> を動的生成 → POST 送信する手法
  • 基本パターンは document.createElement("form") + form.method="POST" + form.action=URL + 各 inputappendChild + document.body.appendChild(form) + form.submit()
  • ページ遷移を伴う送信は form.submit、遷移なしfetch() / XMLHttpRequest
  • ファイル送信は FormData を使い enctype="multipart/form-data" を設定
  • Laravel / Rails 等は CSRF トークンを hidden input で含める必要あり

なぜ JavaScript だけで form を作るのか

HTML に <form> を書かず、JavaScript で動的にフォームを組み立てて POST 送信したい場面は意外と多いです。

  • ボタンクリックだけで別画面へ POST 遷移させたい(GET だとパラメータが URL に出る)
  • SPA から外部サイトに POST で飛ばす(決済ゲートウェイ等)
  • 動的に生成したデータをそのまま送信
  • ブックマークレット / ユーザースクリプトから送信

最小コード

function postSubmit(url, params) {
  const form = document.createElement('form');
  form.method = 'POST';
  form.action = url;

  for (const key in params) {
    const input = document.createElement('input');
    input.type = 'hidden';
    input.name = key;
    input.value = params[key];
    form.appendChild(input);
  }

  document.body.appendChild(form);
  form.submit();
}

// 利用例
postSubmit('/order/confirm', {
  product_id: 123,
  qty: 2,
  coupon: 'SPRING20'
});

このコードを実行すると、ブラウザは /order/confirmPOST で画面遷移します。HTML の <form> をクリックしたのと完全に同じ挙動です。

各プロパティの意味

プロパティ説明
form.methodPOST / GETHTTP メソッド。デフォルト GET
form.actionURL送信先。相対 / 絶対どちらも可
form.target_self / _blank送信結果の表示先。新タブで開きたいときは _blank
form.enctypeapplication/x-www-form-urlencoded / multipart/form-dataエンコード形式。ファイル送信は後者必須
form.acceptCharsetUTF-8文字コード

document.body.appendChild は必要か

はい、必要です。DOM ツリーに接続されていない form は submit できません(一部ブラウザで silently fail)。送信後すぐ削除する場合:

document.body.appendChild(form);
form.submit();
// submit() 後にすぐ navigation が始まるので不要だが、
// target=_blank で残したくない場合:
form.remove();

CSRF トークンを含める(Laravel / Rails)

Laravel は <meta name="csrf-token" content="..."> をレイアウトに置く慣習があります:

function postWithCsrf(url, params) {
  const token = document.querySelector('meta[name="csrf-token"]').content;

  const form = document.createElement('form');
  form.method = 'POST';
  form.action = url;

  // Laravel の _token フィールド
  const csrfInput = document.createElement('input');
  csrfInput.type = 'hidden';
  csrfInput.name = '_token';
  csrfInput.value = token;
  form.appendChild(csrfInput);

  for (const key in params) {
    const input = document.createElement('input');
    input.type = 'hidden';
    input.name = key;
    input.value = params[key];
    form.appendChild(input);
  }

  document.body.appendChild(form);
  form.submit();
}

Rails は authenticity_token という名前、Django は csrfmiddlewaretoken。フレームワークごとに名前が違うので注意。

PUT / DELETE / PATCH を送りたい

HTML 標準の form は GET / POST しか送信できません。Laravel / Rails では _method hidden field を使った method spoofing が定番:

function deleteForm(url) {
  const form = document.createElement('form');
  form.method = 'POST';
  form.action = url;

  // Laravel の method spoofing
  const methodInput = document.createElement('input');
  methodInput.type = 'hidden';
  methodInput.name = '_method';
  methodInput.value = 'DELETE';
  form.appendChild(methodInput);

  // CSRF も忘れずに
  const token = document.querySelector('meta[name="csrf-token"]').content;
  const csrf = document.createElement('input');
  csrf.type = 'hidden';
  csrf.name = '_token';
  csrf.value = token;
  form.appendChild(csrf);

  document.body.appendChild(form);
  form.submit();
}

ファイルを送信したい(FormData)

動的 form はバイナリを直接持てないため、fetch + FormData を使うのが現代的:

async function uploadFile(url, file, extraParams = {}) {
  const fd = new FormData();
  fd.append('file', file);
  for (const k in extraParams) fd.append(k, extraParams[k]);

  const token = document.querySelector('meta[name="csrf-token"]').content;

  const res = await fetch(url, {
    method: 'POST',
    headers: { 'X-CSRF-TOKEN': token },
    body: fd,
  });
  return res.json();
}

// 利用例(input[type=file] から取得)
const fileInput = document.querySelector('#file');
fileInput.addEventListener('change', e => {
  uploadFile('/upload', e.target.files[0], { user_id: 1 })
    .then(json => console.log(json));
});

form.submit() と fetch() の使い分け

用途form.submit()fetch()
ページ遷移○ 起きる× 起きない
サーバ応答を JS で受ける×
ファイル送信○ (multipart 設定要)○ (FormData)
クロスオリジン○ (リダイレクトは見れる)○ (CORS 設定要)
決済ゲートウェイ POST○ 推奨× CORS で弾かれる
SPA 内部 API×○ 推奨

配列パラメータの送信

PHP / Laravel は name="tags[]" 形式で配列を受け取ります:

function appendArray(form, name, values) {
  values.forEach(v => {
    const input = document.createElement('input');
    input.type = 'hidden';
    input.name = name + '[]'; // tags[]
    input.value = v;
    form.appendChild(input);
  });
}

const form = document.createElement('form');
form.method = 'POST';
form.action = '/search';
appendArray(form, 'tags', ['php', 'laravel', 'vue']);
document.body.appendChild(form);
form.submit();
// → POST /search  tags[]=php&tags[]=laravel&tags[]=vue

よくある落とし穴

  • form を appendChild しない → ブラウザによっては submit() が無視される
  • input.value に objet を入れる[object Object] の文字列になる。事前に JSON.stringify
  • 改行を含む値 → hidden input でも保持される。サーバ側で正しく受け取れているか確認
  • CSRF 忘れ → 419 Page Expired / 422 になる
  • 同じ name を 2 つ → 後勝ち。配列にしたければ name[]

FAQ

Q: GET でも同じやり方でできる?
A: できます。form.method = "GET" にするだけ。ただし GET は URL にパラメータが付くので、長すぎる値や秘匿情報は POST にすべき。

Q: window.location.href で POST はできる?
A: できません。location.href は GET 専用。POST 遷移したい場合は form を動的生成するこの方法が唯一の手段です。

Q: jQuery でも同じことできる?
A: $("<form>").attr({method:"POST",action:url}).append(...).appendTo("body").submit() で同じ。ただし現代は Vanilla で十分。