JavaScriptでフォームデータを全て取得してボタンのデータも付けてPost送信
よくあるはずだけど検索に引っかからず
ウェブフォームに入力中にEnterキーを押したら思っていなかったタイミングで思っていなかったボタンがSubmit!!
英文字入力用に開発がメインのウェブ世界、Enterキーで漢字変換などを確定するなんていう作業は想定外なんでしょうね。
ネット上にはボタン一個でフォームの中身だけを非同期で送るみたいのはたくさん見つかるのですが、ボタンたくさんで、というのが見当たらず思い付かずだったので、これの回避方法の備忘録。
目次を読んでもらえるとほぼ内容把握できます。
ChatGPT様に聞いてみた
ここはやはりまずは聞いてみようよChatGPT様に!
function submitFormWithFetch() {
const form = document.getElementById('myForm'); // フォームのIDを取得
const formData = new FormData(form);
fetch(form.action, {
method: 'POST',
body: formData
})
.then(response => {
if (response.ok) {
return response.text(); // またはJSONなど、必要に応じて
} else {
throw new Error('送信に失敗しました。');
}
})
.then(data => {
// ここでページ遷移を行う
window.location.href = 'success_page.html'; // 遷移先のURLを指定
})
.catch(error => {
console.error('エラー:', error);
});
}
うーん、それだとフォーム送ってそれを次のページで受け取ることができないじゃない。
function submitForm() {
// フォーム要素を取得
var form = document.getElementById('myForm');
// フォームのsubmitイベントをプログラム的にトリガーする
form.submit();
}
うーん、模倣する、ということはまねするということだからできそうだけどちゃんとはできないってこと? これをこのまま送信するとフォームタグを含めた状態で送られてしまうから先方でまた解体作業して組み立ててと面倒な話。
普通にbutton type="submit"と同じ挙動にしたいのです。
ま、ともかく作っていきましょう。
ページの中にボタンがいくつもある状態を
ページの中にあれやこれやのボタンが設置してあるのです。例えば個人情報の書き換えのページで、パスワードの書き換えは別なページで処理したいからそっち行きのボタンもそこにある、みたいな。
そしてどのボタンが押されたのかを判明したい値がそのボタンのvalueに書いてあります。
JavaScriptで制御します
まずはtype="submit" にしてあるボタンを全て type="button"にします。時々<form>にonSubmit="return false;"を入れるというのを見かけますが、typeを全てbuttonにしてあればこの必要はないです。だって、Submitボタンが無いですからその指示が発火することないですし。。。
<form method="post" id="myForm">
--ここにいろいろフォーム内容--
<button type="button" name="act" value="send"> 送る </button>
<button type="button" name="act" value="other"> フォーム以外のこと </button>
</form>
ボタンの中にonClick="関数名()";を入れて
この関数名、フォームのSubmitの関数をするのだから onClick="submit();" にしちゃえ、は絶対ダメです。なぜなら、submit()というのはすでに挙動が決まっている関数。そしてその挙動は<<<submit>>>>そのもの!!
せっかくtype="button"にしたのにJavaScriptでsubmit()しかも何にも引き連れて行かない(=フォームデータを送らない)submitボタンの出来上がり、なんて悲しすぎる結末に。。。
ここはひとつsendform()という関数名を付けて進めてみましょう。
<button type="button" name="act" value="send" onClick="sendform();"> 送る </button>
<button type="button" name="act" value="other" onClick="sendform();"> フォーム以外のこと </button>
function sendform(){
}
関数の中身を書いていきます
作ったフォームの名前jsfrmはJavaScript formから考えたもの。いつも思うのだけれど、formとfromは似てるな、と。。。frmと略すとどっちかわからない。。。
function sendform(){
var jsfrm = document.createElement("form");
jsfrm.setAttribute("action", "ここは移動先のURLを入れます 絶対でも相対でも大丈夫");
jsfrm.setAttribute("method", "post");
jsfrm.style.display = "none";
document.body.appendChild(jsfrm);
}
input = 'hidden"にするけど念の為にdisplay = "none"
jsfrm.style.display = "none";
も入れました。
どのボタンをクリックしたか判明させるために(this.value)
今回の一番の目的はどのボタンをクリックしたのかを判明すること。なので、ボタンに書いたonClick = sendform()の括弧の中にthis.valueと記入。
<button type="button" name="act" value="send" onClick="sendform(this.value);"> 送る </button>
<button type="button" name="act" value="other" onClick="sendform(this.value);"> フォーム以外のこと </button>
受け取る関数にも function sendform(n){
受け取り側にも代入のための文字を適当に入れます。今回はnを使用しよう。
function sendform(n){
var jsfrm = document.createElement("form");
jsfrm.setAttribute("action", "ここは移動先のURLを入れます 絶対でも相対でも大丈夫");
jsfrm.setAttribute("method", "post");
jsfrm.style.display = "none";
document.body.appendChild(jsfrm);
}
ボタンのvalueをjsformに加えます
関数の中にちょっとずつ足してフォームを完成させていきます。
var input = document.createElement('input');
input.setAttribute('type', 'hidden');
input.setAttribute('name', 'act'); //もともとのボタンに付いていたボタンの名前
input.setAttribute('value', n); //ここでボタンから送られてきたthis.valueの値を入れます
jsfrm.appendChild(input);
フォームの中身を全て取得
ボタンデータだけではなく、フォームの中身も手に入れます。
const data = new FormData(myForm);
for文で回します
取得したフォーム、記入欄が一つならforは不要ですが、まずそんなことはないでしょう。すべてをjsfrmに格納していきます。
for (let entry of data) {
let input = document.createElement('input');
input.setAttribute('type', 'hidden');
input.setAttribute('name', entry[0]);
input.setAttribute('value', entry[1]);
jsfrm.appendChild(input);
}
完成です
できました。JavaScriptに精通されている方ならなんてことはないでしょうし、勘の良い方ならここまでの記事で実装できてしまうでしょう。でもここは敢えて完成形の表示は100円とさせていただきます。だって私の5時間くらいの作業、それをたったの100円!! 応援感覚で投げ銭して(買って)ください。
しかし、<input type="text">がひとつだけだとEnterでまだ何かをSubmitしているみたい
これについての強制回避も以下の部分に書きました。
ここから先は
¥ 100
この記事が気に入ったらチップで応援してみませんか?