179

サーバーが処理するのに少し時間がかかるフォームがあります。ユーザーが待機し、ボタンをもう一度クリックしてフォームを再送信しようとしないようにする必要があります。次のjQueryコードを使用してみました。

<script type="text/javascript">
$(document).ready(function() {
    $("form#my_form").submit(function() {
        $('input').attr('disabled', 'disabled');
        $('a').attr('disabled', 'disabled');
        return true;
    });
});
</script>

Firefoxでこれを試してみると、すべてが無効になりますが、フォームには、含まれているはずのPOSTデータが送信されません。複数の送信ボタンがあり、POSTに含まれる値にどのボタンが使用されたかを判断するため、フォームと一緒にボタンを送信する必要があるため、jQueryを使用してフォームを送信できません。フォームを通常どおりに送信する必要があり、その直後にすべてを無効にする必要があります。

ありがとう!

4

24 に答える 24

332

2018年の更新:この古い回答についていくつかのポイントを得たので、重複した送信が無害になるように操作をべき等にすることが最善の解決策であることを追加したかっただけです。

たとえば、フォームが注文を作成する場合、一意の ID をフォームに入れます。サーバーは、その ID を持つ注文作成リクエストを初めて確認すると、それを作成して「成功」と応答する必要があります。後続の送信も「成功」と応答する必要がありますが (クライアントが最初の応答を取得しなかった場合)、何も変更しないでください。

競合状態を防ぐために、データベース内の一意性チェックによって重複を検出する必要があります。


あなたの問題はこの行だと思います:

$('input').attr('disabled','disabled');

フォームが送信するはずのデータを含むすべての入力を無効にしています。

送信ボタンだけを無効にするには、次のようにます。

$('button[type=submit], input[type=submit]').prop('disabled',true);

ただし、これらのボタンが無効になっている場合でも、IEがフォームを送信するとは思いません。別のアプローチをお勧めします。

それを解決するjQueryプラグイン

次のコードでこの問題を解決しました。ここでの秘訣は、jQuery を使用しdata()て、フォームが送信済みかどうかをマークすることです。そうすれば、送信ボタンをいじる必要がなくなります。

// jQuery plugin to prevent double submission of forms
jQuery.fn.preventDoubleSubmission = function() {
  $(this).on('submit',function(e){
    var $form = $(this);

    if ($form.data('submitted') === true) {
      // Previously submitted - don't submit again
      e.preventDefault();
    } else {
      // Mark it so that the next submit can be ignored
      $form.data('submitted', true);
    }
  });

  // Keep chainability
  return this;
};

次のように使用します。

$('form').preventDoubleSubmission();

ページの読み込みごとに複数回の送信を許可する必要がある AJAX フォームがある場合は、それを示すクラスを指定して、次のようにセレクターから除外できます。

$('form:not(.js-allow-double-submission)').preventDoubleSubmission();
于 2010-12-17T18:48:58.767 に答える
49

タイミングアプローチが間違っています-アクションがクライアントのブラウザでどのくらいの時間がかかるかをどうやって知るのですか?

どうやってするの

$('form').submit(function(){
  $(this).find(':submit').attr('disabled','disabled');
});

フォームが送信されると、内部のすべての送信ボタンが無効になります。

Firefoxでは、ボタンを無効にすると、履歴に戻ったときにこの状態が記憶されることを忘れないでください。これを防ぐには、たとえば、ページの読み込み時にボタンを有効にする必要があります。

于 2012-07-25T12:12:08.140 に答える
20

ネイサン・ロングの答えが道だと思います。私にとっては、クライアント側の検証を使用しているため、フォームが有効であるという条件を追加しました。

EDIT : これが追加されていない場合、クライアント側の検証でエラーが発生した場合、ユーザーはフォームを送信できません。

        // jQuery plugin to prevent double submission of forms
        jQuery.fn.preventDoubleSubmission = function () {
            $(this).on('submit', function (e) {
                var $form = $(this);

                if ($form.data('submitted') === true) {
                    // Previously submitted - don't submit again
                    alert('Form already submitted. Please wait.');
                    e.preventDefault();
                } else {
                    // Mark it so that the next submit can be ignored
                    // ADDED requirement that form be valid
                    if($form.valid()) {
                        $form.data('submitted', true);
                    }
                }
            });

            // Keep chainability
            return this;
        };
于 2014-06-16T00:31:32.193 に答える
9

event.timeStampFirefox では動作しません。false を返すことは非標準です。 を呼び出す必要がありますevent.preventDefault()。そして、私たちがそれに取り組んでいる間、常に制御構文で中括弧を使用してください。

これまでのすべての回答を要約すると、これが仕事をし、クロスブラウザーで動作するプラグインです。

jQuery.fn.preventDoubleSubmission = function() {

    var last_clicked, time_since_clicked;

    jQuery(this).bind('submit', function(event) {

        if(last_clicked) {
            time_since_clicked = jQuery.now() - last_clicked;
        }

        last_clicked = jQuery.now();

        if(time_since_clicked < 2000) {
            // Blocking form submit because it was too soon after the last submit.
            event.preventDefault();
        }

        return true;
    });
};

Kern3l に対処するために、送信ボタンのダブルクリックを停止しようとしているという理由だけで、タイミング メソッドが機能します。送信に対する応答時間が非常に長い場合は、送信ボタンまたはフォームをスピナーに置き換えることをお勧めします。

上記の例のほとんどがそうであるように、フォームの後続の送信を完全にブロックすると、悪い副作用が 1 つあります。ネットワーク障害が発生し、再送信しようとしても、再送信できず、変更内容が失われます。作る。これは間違いなくユーザーを怒らせるでしょう。

于 2013-02-22T19:00:07.933 に答える
8

jquery-safeformプラグインをチェックしてください。

使用例:

$('.safeform').safeform({
    timeout: 5000,  // disable next submission for 5 sec
    submit: function() {
        // You can put validation and ajax stuff here...

        // When done no need to wait for timeout, re-enable the form ASAP
        $(this).safeform('complete');
        return false;
    }
});
于 2015-01-19T23:18:01.883 に答える
4

ネイサンロングのアプローチを改善する可能性があります。すでに送信されたフォームを検出するためのロジックを次のロジックに置き換えることができます。

var lastTime = $(this).data("lastSubmitTime");
if (lastTime && typeof lastTime === "object") {
    var now = new Date();
    if ((now - lastTime) > 2000) // 2000ms
        return true;
    else
        return false;
}
$(this).data("lastSubmitTime", new Date());
return true; // or do an ajax call or smth else
于 2011-10-30T07:45:46.590 に答える
4

...しかし、フォームは、含まれているはずの POST データとともに送信されません。

正しい。無効化されたフォーム要素の名前/値はサ​​ーバーに送信されません。それらを読み取り専用要素として設定する必要があります。

また、アンカーをそのように無効にすることはできません。HREF を削除するか (推奨されません)、デフォルトの動作を防止する (より良い方法) 必要があります。たとえば、次のようになります。

<script type="text/javascript">
$(document).ready(function(){
    $("form#my_form").submit(function(){
      $('input').attr('readonly', true);
      $('input[type=submit]').attr("disabled", "disabled");
      $('a').unbind("click").click(function(e) {
          e.preventDefault();
          // or return false;
      });
    });
</script>
于 2010-05-13T21:48:19.333 に答える
4

ネイサンのコードですが、jQuery Validate プラグイン用です

jQuery Validate プラグインを使用する場合、それらには既にサブミット ハンドラーが実装されているため、複数実装する必要はありません。コード:

jQuery.validator.setDefaults({
  submitHandler: function(form){
    // Prevent double submit
    if($(form).data('submitted')===true){
      // Previously submitted - don't submit again
      return false;
    } else {
      // Mark form as 'submitted' so that the next submit can be ignored
      $(form).data('submitted', true);
      return true;
    }
  }
});

ブロック内で簡単に展開して、} else {入力や送信ボタンを無効にすることができます。

乾杯

于 2015-04-21T09:14:45.390 に答える
2

AJAXを使用してフォームを投稿する場合、setasync: falseはフォームがクリアされる前に追加の送信を防止する必要があります。

$("#form").submit(function(){
    var one = $("#one").val();
    var two = $("#two").val();
    $.ajax({
      type: "POST",
      async: false,  // <------ Will complete submit before allowing further action
      url: "process.php",
      data: "one="+one+"&two="+two+"&add=true",
      success: function(result){
        console.log(result);
        // do something with result
      },
      error: function(){alert('Error!')}
    });
    return false;
   }
});
于 2013-06-22T06:01:45.007 に答える
2

2 つの送信ボタンを使用します。

<input id="sub" name="sub" type="submit" value="OK, Save">
<input id="sub2" name="sub2" type="submit" value="Hidden Submit" style="display:none">

そしてjQuery:

$("#sub").click(function(){
  $(this).val("Please wait..");
  $(this).attr("disabled","disabled");
  $("#sub2").click();
});
于 2015-04-18T11:07:30.097 に答える
2

これで2回目の送信を停止できます

$("form").submit(function() {
        // submit more than once return false
        $(this).submit(function() {
            return false;
        });
        // submit once return true
        return true; // or do what you want to do
    });
});
于 2019-07-02T11:49:38.823 に答える
2

この投稿のアイデアを使用して、AtZako のバージョンと非常によく似たソリューションを考え出しました。

 jQuery.fn.preventDoubleSubmission = function() {

    var last_clicked, time_since_clicked;

    $(this).bind('submit', function(event){

    if(last_clicked) 
      time_since_clicked = event.timeStamp - last_clicked;

    last_clicked = event.timeStamp;

    if(time_since_clicked < 2000)
      return false;

    return true;
  });   
};

次のように使用します。

$('#my-form').preventDoubleSubmission();

ロックアウトがトリガーされると、ページを更新するまで再度送信できないため、何らかのタイムアウトを含まず、送信を無効にするか、フォーム要素を無効にするだけのソリューションが問題を引き起こすことがわかりました。これは、ajax を行うときにいくつかの問題を引き起こします。

これはそれほど派手ではないので、おそらく少しきれいにすることができます.

于 2012-06-12T04:07:11.660 に答える
1

私は同様の問題を抱えており、私の解決策は次のとおりです。

クライアント側の検証がない場合は、ここに記載されているように jquery one() メソッドを使用できます。

http://api.jquery.com/one/

これにより、呼び出された後にハンドラーが無効になります。

$("#mysavebuttonid").on("click", function () {
  $('form').submit();
});

私が行っていたようにクライアント側の検証を行っている場合は、もう少し注意が必要です。上記の例では、検証に失敗した後に再度送信することはできません。代わりにこのアプローチを試してください

$("#mysavebuttonid").on("click", function (event) {
  $('form').submit();
  if (boolFormPassedClientSideValidation) {
        //form has passed client side validation and is going to be saved
        //now disable this button from future presses
        $(this).off(event);
   }
});
于 2015-08-18T15:04:10.077 に答える
0

私の場合、フォームの onsubmit にはいくつかの検証コードが含まれていたので、onsubmit チェックポイントを含むNathan Longの回答をインクリメントします。

$.fn.preventDoubleSubmission = function() {
      $(this).on('submit',function(e){
        var $form = $(this);
        //if the form has something in onsubmit
        var submitCode = $form.attr('onsubmit');
        if(submitCode != undefined && submitCode != ''){
            var submitFunction = new Function (submitCode);
            if(!submitFunction()){
                event.preventDefault();
                return false;
            }                   
        }

        if ($form.data('submitted') === true) {
            /*Previously submitted - don't submit again */
            e.preventDefault();
        } else {
          /*Mark it so that the next submit can be ignored*/
          $form.data('submitted', true);
        }
      });

      /*Keep chainability*/
      return this;
    };
于 2015-08-18T09:13:24.120 に答える
0

私の解決策:

// jQuery plugin to prevent double submission of forms
$.fn.preventDoubleSubmission = function () {
    var $form = $(this);

    $form.find('[type="submit"]').click(function () {
        $(this).prop('disabled', true);
        $form.submit();
    });

    // Keep chainability
    return this;
};
于 2015-08-17T09:54:24.787 に答える
0

ポインターイベントの古き良き CSS トリックは信じられません。まだ言及されていません。無効な属性を追加することで同じ問題が発生しましたが、これはポストバックしません。以下を試して、#SubmitButton を送信ボタンの ID に置き換えてください。

$(document).on('click', '#SubmitButton', function () {
    $(this).css('pointer-events', 'none');
})
于 2018-12-04T11:19:32.130 に答える
-1

以下を使用して、非常によく似た問題を解決しました。

$("#my_form").submit(function(){
    $('input[type=submit]').click(function(event){
        event.preventDefault();
    });
});
于 2011-07-13T19:17:10.753 に答える