応答が遅い場合、送信ボタンを複数回クリックすることがあります。
これを防ぐにはどうすればよいですか?
控えめな JavaScript を使用して、フォームが送信された後にフォームの送信イベントを無効にします。jQueryを使った例です。
編集: 送信ボタンをクリックせずにフォームを送信する際の問題を修正しました。ありがとう、いちばん。
$("body").on("submit", "form", function() {
$(this).submit(function() {
return false;
});
return true;
});
vanstee のソリューションと asp mvc 3 の目立たない検証を試してみました。クライアントの検証が失敗した場合でも、コードは実行され、フォームの送信は完全に無効になります。フィールドを修正した後、再送信できません。(bjanのコメントを参照)
そこで、vanstee のスクリプトを次のように変更しました。
$("form").submit(function () {
if ($(this).valid()) {
$(this).submit(function () {
return false;
});
return true;
}
else {
return false;
}
});
クライアント側のフォーム送信コントロールは、onsubmit ハンドラーで送信ボタンを非表示にし、読み込みアニメーションに置き換えることで、非常にエレガントに実現できます。こうすることで、ユーザーはアクション (クリック) が発生した場所で視覚的なフィードバックを即座に得ることができます。同時に、フォームが再度送信されるのを防ぎます。
XHR 経由でフォームを送信する場合は、タイムアウトなどの送信エラーも処理する必要があることに注意してください。ユーザーはフォームを再送信する必要があるため、送信ボタンを再度表示する必要があります。
別の注記として、llimllib は非常に有効なポイントをもたらします。すべてのフォーム検証はサーバー側で行う必要があります。これには、複数の送信チェックが含まれます。クライアントを信用してはいけません!これは、javascript が無効になっている場合だけではありません。クライアント側のコードはすべて変更できることに注意してください。想像するのは少し難しいですが、サーバーと通信する html/javascript は、必ずしもあなたが書いた html/javascript とは限りません。
llimllib が示唆するように、そのフォームに固有の識別子を使用してフォームを生成し、非表示の入力フィールドに配置します。その識別子を保存します。フォームデータを受信すると、識別子が一致した場合にのみ処理されます。(また、識別子をユーザー セッションにリンクし、セキュリティを強化するためにそれを照合します。) データ処理後、識別子を削除します。
もちろん、フォーム データがまったく送信されていない識別子をクリーンアップする必要がある場合もあります。しかし、ほとんどの場合、あなたの Web サイトはすでに何らかの「ガベージ コレクション」メカニズムを採用しています。
これを行う簡単な方法は次のとおりです。
<form onsubmit="return checkBeforeSubmit()">
some input:<input type="text">
<input type="submit" value="submit" />
</form>
<script type="text/javascript">
var wasSubmitted = false;
function checkBeforeSubmit(){
if(!wasSubmitted) {
wasSubmitted = true;
return wasSubmitted;
}
return false;
}
</script>
<form onsubmit="if(submitted) return false; submitted = true; return true">
この質問に対する最も単純な答えは、「応答が遅い場合、送信ボタンを複数回クリックすることがあります。これを防ぐにはどうすればよいですか?」
以下のコードのように、フォーム送信ボタンを無効にするだけです。
<form ... onsubmit="buttonName.disabled=true; return true;">
<input type="submit" name="buttonName" value="Submit">
</form>
送信するための最初のクリックで、送信ボタンを無効にします。また、いくつかの検証ルールがある場合は、正常に機能します。それが役立つことを願っています。
一意の識別子を作成し (たとえば、現在の時刻をハッシュできます)、それをフォームの非表示の入力にします。サーバー側で、各フォーム送信の一意の識別子を確認します。すでにそのハッシュを受け取っている場合は、繰り返し送信されます。ユーザーが再送信する唯一の方法は、フォーム ページをリロードすることです。
編集: JavaScript に依存するのは良い考えではないので、皆さんはそれらのアイデアに賛成票を投じ続けることができますが、一部のユーザーはそれを有効にしないでしょう. 正解は、サーバー側でユーザー入力を信頼しないことです。
クリック後すぐに送信ボタンを無効にします。検証を適切に処理するようにしてください。また、すべての処理または DB 操作の中間ページを保持してから、次のページにリダイレクトします。これにより、2 番目のページを更新しても別の処理が行われないことが保証されます。
進行状況バーまたはスピナーを表示して、フォームが処理中であることを示すこともできます。
JQuery を使用すると、次のことができます。
$('input:submit').click( function() { this.disabled = true } );
&
$('input:submit').keypress( function(e) {
if (e.which == 13) {
this.disabled = true
}
}
);
質問に「javascript」のタグを付けたことは知っていますが、javascript にまったく依存しない解決策を次に示します。
これはPRGという名前の webapp パターンであり、これについて説明する優れた記事があります
次のようにすると、複数の送信を簡単に防ぐことができます。
var Workin = false;
$('form').submit(function()
{
if(Workin) return false;
Workin =true;
// codes here.
// Once you finish turn the Workin variable into false
// to enable the submit event again
Workin = false;
});
クライアント側では、@vanstee と @chaos が提供するメソッドのような JavaScript コードでフォームが送信されたら、送信ボタンを無効にする必要があります。
しかし、これを防ぐために JS に頼るべきではないネットワーク ラグまたは JavaScript が無効な状況には問題があります。
したがって、サーバー側では、同じクライアントからの繰り返し送信を確認し、ユーザーからの誤った試行と思われる繰り返し送信を省略する必要があります。
safeform jquery プラグインを試すことができます。
$('#example').safeform({
timeout: 5000, // disable form on 5 sec. after submit
submit: function(event) {
// put here validation and ajax stuff...
// no need to wait for timeout, re-enable the form ASAP
$(this).safeform('complete');
return false;
}
})
複数の送信を防ぐ最善の方法は、メソッドでボタン ID を渡すことです。
function DisableButton() {
document.getElementById("btnPostJob").disabled = true;
}
window.onbeforeunload = DisableButton;
JavaScript を使用してこれを行うのは少し簡単です。以下は、必要な機能を提供するコードです。
$('#disable').on('click', function(){
$('#disable').attr("disabled", true);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="disable">Disable Me!</button>