HTML フォームの送信

HTML フォームの送信2 分で読めます

HTML フォームの action 属性を解説

フォームの action 属性の役割、相対値や空の値の解決のされ方、formaction で 1 つのフォームを 2 か所に送る方法、静的ホストが 405 を返す理由を解説します。

Preet SutharIkiform 創業者

action 属性は、フォームがデータを送る URL です。相対値はページのアドレスを基準に解決され、空または未指定ならページ自身を指し、送信ボタンの formaction はそのボタンについてだけ上書きします。静的サイトでは、自分のホストは POST を受けられないので、https://ikiform.com/f/<formId> のようなフォームバックエンドの完全な URL を設定してください。

静的サイトで壊れているフォームのほとんどは、この 1 つの属性が原因です。マークアップは問題なく見え、ボタンも動くのに、ブラウザーには 405 か空白のページが表示されます。データが受け取れない場所に送られたからです。このページでは、ある action がデータをどこに送るのかを正確に示し、そのうえで formaction を使って 1 つのフォームを 2 つの受信先に振り分けます。

ここが違う

action はどの href とも同じ URL ですが、1 つだけ癖があります。action のないフォームは何もしないのではなく、自分が置かれたページに送信します。サーバーレンダリングのサイトなら、そのページが送信を処理するかもしれません。静的ホストでは処理できないので、action がない、または相対値だと、デプロイしてから初めて失敗します。

値ごとのデータの送り先

https://example.com/company/contact.html にあるページと、そこに置いた 5 つのフォームを例にします。

contact.html
<form action="https://ikiform.com/f/frm_xxxxxxxxxxxxxxxx" method="post">
<form action="/api/contact" method="post">
<form action="send" method="post">
<form action="" method="post">
<form method="post">
action解決後静的ホストでは
https://ikiform.com/f/frm_...その URL のまま動きます。Ikiform が POST を受けます
/api/contacthttps://example.com/api/contactそのパスで関数を実行するホストでのみ動きます
sendフォルダー基準で https://example.com/company/send405 か 404
"" (empty)ページ自身、contact.htmlほとんどの静的ホストで 405
未指定ページ自身ほとんどの静的ホストで 405
ブラウザーがフォームの action 属性を送信先の URL に変える流れ絶対相対、空、未指定action="https://ikiform.com/f/..."そのまま使用Ikiform が 303 を返すaction="send" か未指定ページ基準で解決ページに <base href>があればそれが基準自分の静的ホストPOST 不可:405ブラウザーがフォームの action 属性を送信先の URL に変える流れ絶対相対、空、未指定action="https://ikiform.com/f/..."そのまま使用Ikiform が 303 を返すaction="send" か未指定ページ基準で解決ページに <base href> があればそれが基準自分の静的ホストPOST 不可:405
  1. 絶対 URL の action は書かれたとおりに使われるので、送信は Ikiform に届き、Ikiform はリダイレクトを返します。
  2. 相対、空、未指定の action は、ページ自身のアドレス、またはページに base 要素があればそれを基準に解決されます。
  3. そのため送信は自分のホストに向かいます。静的ホストはファイルを配信するだけなので、POST を拒否します。たいていは 405 です。
送信直後のアドレスバーに自分のドメインが表示されていれば、action は相対値でした。
ページの head にある <base href> 要素は、action を含むすべての相対 URL の解決方法を変えます。サイトビルダーやシングルページアプリの構成によっては、これを追加するものがあります。完全な URL を使えば影響はありません。

ブラウザーが使う値を確認する

ブラウザーのコンソールでは、属性とプロパティが異なります。getAttribute は書いたとおりの値を返し、action プロパティはブラウザーが実際に送信する解決済みの URL を返します。

コンソール
const form = document.querySelector("form");
form.getAttribute("action");
form.action;

form.action に自分のドメインが表示されたら、データはそこに送られます。Webflow や Framer などのビルダーは、自身の設定パネルから action を設定することが多いので、ソースではなく公開済みのページを確認してください。各ビルダーがどこにそれを持っているかはサイトビルダーのガイドにあります。

1 つのフォーム、2 つの受信先

送信ボタンの formaction は、そのボタンについてだけフォームの action を置き換えます。ここでは、1 組のフィールドを 2 つの Ikiform フォームに送ります。Ask support はサポートフォームに、Talk to sales は営業フォームに送信し、各 Ikiform フォームはそれぞれの宛先にメールを送ります。

contact.html
<form action="https://ikiform.com/f/frm_supportxxxxxxxxx" method="post">
  <label for="email">Email</label>
  <input id="email" name="email" type="email" autocomplete="email" required />

  <label for="message">How can we help?</label>
  <textarea id="message" name="message" rows="5" required></textarea>

  <input name="_gotcha" type="text" tabindex="-1" autocomplete="off" hidden />
  <button>Ask support</button>
  <button formaction="https://ikiform.com/f/frm_salesxxxxxxxxxxx">Talk to sales</button>
</form>
  • Ikiform のフォームはそれぞれ通知の受信者、スパム設定、Webhook を持つので、サポートと営業が互いのメールを目にすることはありません。
  • 両方のフォームに同じフィールド定義を設定するか、どちらにも設定しないでください。フィールドを定義すると、そのフォームが知らないフィールドは 422 で拒否されます。
  • ほかの form* 属性も同じように動作します: formmethod、formenctype、formnovalidate、formtarget です。formnovalidate を付けた Save draft ボタンは、ブラウザーのチェックをスキップします。
  • formaction が使えるのは送信ボタンだけです: <button>、<input type="submit">、<input type="image"> です。

別の方法として、topic フィールドを持つ Ikiform のフォーム 1 つにまとめ、Webhook や受信箱のフィルターでトピックごとに振り分けることもできます。そうすればリストもエクスポートも 1 つで済みます。2 つのチームで受信者をまったく共有すべきでないなら、フォームを 2 つにするほうがシンプルです。

クエリ文字列付きの action

method="get" では、ブラウザーは action のクエリ文字列をフォームのフィールドで置き換えます。下の 1 つ目のフォームの lang=de は黙って捨てられます。2 つ目は hidden input として残しています:

search.html
<form action="/search?lang=de" method="get">
  <input name="q" />
</form>

<form action="/search" method="get">
  <input name="q" />
  <input type="hidden" name="lang" value="de" />
</form>

method="post" では、フィールドはボディに入るので、クエリ文字列は残ります。ただし Ikiform では何も変わりません。エンドポイント URL のクエリパラメーターは保存されないので、残したい値には hidden input を使ってください。

フォームの外にある入力欄

レイアウトによっては、ほかのコンテンツの隣に置くフッターの登録欄のように、<form> 要素の中にない入力欄が必要になることがあります。入力欄やボタンの form 属性は、id でフォームに結び付け、そのフォームの action に送信します:

footer.html
<form id="newsletter" action="https://ikiform.com/f/frm_xxxxxxxxxxxxxxxx" method="post"></form>

<footer>
  <input form="newsletter" name="email" type="email" required />
  <button form="newsletter">Subscribe</button>
</footer>

mailto: と javascript: の action

action="mailto:you@example.com" は、訪問者のメールアプリにフィールド入りのメッセージを開かせます。メールアプリが設定されていて送信ボタンを押さない限り何も送られず、送ろうとしたことすらあなたにはわかりません。action="javascript:..." は送信せずにコードを実行し、ほとんどのコンテンツセキュリティポリシーでブロックされます。どちらも本物のエンドポイントに置き換える価値があります。

動作を確認する

  1. フォームの Allowed domains に自分のサイトのドメインを追加し、開発中は localhost も追加します。空のままにすると、どこからの送信も受け付けます。
  2. ソースではなく公開されたページを開き、コンソールで document.querySelector("form").action を実行します。Ikiform の完全な URL が表示されます。
  3. フォームを送信します。Network パネルには、自分のドメインへの POST ではなく、303 が返された ikiform.com への POST が表示されます。
  4. 受信箱が 2 つのフォームで、それぞれのボタンで 1 回ずつ送信します。各送信データは、ダッシュボードでそれぞれのフォームの下に表示されます。
  5. 通知の各受信者の受信トレイを確認します。それぞれにフィールド入りのメールが届き、フォームに email フィールドがあれば Reply で送信者に返信できます。

ハマりどころ

問題原因と対処
自分のドメインから 405 Method Not Allowedaction が相対パス、空、または欠けているので、送信が静的ホストに届いています。Ikiform の完全な URL を使ってください
ikiform.com から 404 not_foundaction のフォーム ID が間違っているか、フォームが削除されています。ダッシュボードのフォームのページからエンドポイントをコピーしてください
ビルダーが action を何度もリセットするフォームブロックの action をビルダーが管理していることがあります。ビルダーのカスタム action の設定か、自分のマークアップを使った埋め込みを使ってください
ブラウザーがフォームは安全でないと警告するhttps: のページで action が http: を使っています。Ikiform のエンドポイントは https: のみです。スキームを修正してください
2 つ目のフォームのフィールドも送信されるフォームは入れ子にできません。ブラウザーは内側の <form> タグで外側のフォームを閉じます。代わりに form 属性を使ってください

クリックからリダイレクトまでの送信の流れ全体は概要を参照してください。エンドポイントが受け付けるものはすべて HTML フォームにあります。

よくある質問

手順で詰まったときや、あなたの状況に合うガイドがほしいときはメールでどうぞ: hello@ikiform.com