代码之家  ›  专栏  ›  技术社区  ›  Adam

防止在jQuery中重复提交表单

  •  155
  • Adam  · 技术社区  · 14 年前

    我有一个表单,需要服务器处理一段时间。我需要确保用户等待并且不会再次单击按钮尝试重新提交表单。我尝试使用以下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数据。我不能使用jQuery来提交表单,因为我需要将按钮与表单一起提交,因为有多个提交按钮,并且我确定哪个按钮被使用,哪个按钮的值包含在文章中。我需要的形式是提交,因为它通常是,我需要禁用一切后,发生了。

    谢谢!

    21 回复  |  直到 5 年前
        1
  •  325
  •   Community pid    4 年前

    2018年更新 最好的 解决方法是使操作幂等,以便重复提交是无害的。

    应通过数据库中的唯一性检查来检测重复项,以防止出现争用情况。


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

    你禁用了所有的输入,包括表单应该提交的数据。

    要仅禁用“提交”按钮,请 能够 请执行以下操作:

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

    然而,我不认为IE会提交的形式,即使这些按钮被禁用。我建议换一种方法。

    一个jQuery插件来解决这个问题

    我们刚刚用下面的代码解决了这个问题。这里的技巧是使用jQuery的 data() 将表格标记为已提交或未提交。这样,我们就不必乱动提交按钮,这会让IE抓狂。

    // 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();
    
        2
  •  47
  •   Ctrl-C Shane Holloway    11 年前

    怎么做

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

    当表单提交时,它将禁用里面的所有提交按钮。

        3
  •  20
  •   PTK    10 年前

    编辑

            // 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;
            };
    
        4
  •  9
  •   Community pid    7 年前

    event.timeStamp 在Firefox中不起作用。返回false是不标准的,您应该致电 event.preventDefault() . 当我们这么做的时候, always use braces with a control construct .

    为了总结前面的所有答案,这里有一个插件,可以跨浏览器工作。

    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,计时方法对我来说很有效,因为我们试图停止双击submit按钮。如果您对提交有很长的响应时间,我建议用微调器替换提交按钮或表单。

        5
  •  8
  •   Max Kamenkov    10 年前

    请退房 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;
        }
    });
    
        6
  •  4
  •   karim79    14 年前

    …但表格未随附 任何应该发布的数据 包括。

    只读 元素。

    而且,不能像那样禁用锚点。您需要删除他们的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>
    
        7
  •  4
  •   Community pid    7 年前

    approach .

    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
    
        8
  •  4
  •   Slava    9 年前

    Nathan的代码,但用于jQuery验证插件

    如果您碰巧使用jqueryvalidate插件,那么它们已经实现了提交处理程序,在这种情况下,没有理由实现多个。代码:

    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 { -阻止以禁用输入和/或提交按钮。

        9
  •  2
  •   jacklin    12 年前

    最后,我利用这篇文章中的想法想出了一个与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的时候带来了一些问题。

    这可能是装饰了一点,因为它不是那么花哨。

        10
  •  2
  •   Al Kari    11 年前

    如果使用 AJAX async: 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;
       }
    });
    
        11
  •  2
  •   AlexZ    10 年前

    对Nathan的bootstrap3的解决方案做了一点修改。这将为submit按钮设置一个加载文本。此外,它将在30秒后超时,并允许重新提交表单。

    jQuery.fn.preventDoubleSubmission = function() {
      $('input[type="submit"]').data('loading-text', 'Loading...');
    
      $(this).on('submit',function(e){
        var $form = $(this);
    
        $('input[type="submit"]', $form).button('loading');
    
        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);
          $form.setFormTimeout();
        }
      });
    
      // Keep chainability
      return this;
    };
    
    jQuery.fn.setFormTimeout = function() {
      var $form = $(this);
      setTimeout(function() {
        $('input[type="submit"]', $form).button('reset');
        alert('Form failed to submit within 30 seconds');
      }, 30000);
    };
    
        12
  •  2
  •   umutkeskin    9 年前

    使用两个提交按钮。

    <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();
    });
    
        13
  •  2
  •   Mr. Mak    6 年前

        var submitCounter = 0;
        function monitor() {
            submitCounter++;
            if (submitCounter < 2) {
                console.log('Submitted. Attempt: ' + submitCounter);
                return true;
            }
            console.log('Not Submitted. Attempt: ' + submitCounter);
            return false;
        }
    

    打电话给我 monitor() 提交表单的函数。

        <form action="/someAction.go" onsubmit="return monitor();" method="POST">
            ....
            <input type="submit" value="Save Data">
        </form>
    
        14
  •  1
  •   mattbloke    9 年前

    如果您没有任何客户端验证,那么您可以简单地使用jqueryone()方法,如本文所述。

    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);
       }
    });
    
        15
  •  1
  •   Mohammed Zayan    5 年前

    你可以通过这个停止第二次提交

    $("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
        });
    });
    
        16
  •  0
  •   user1672591 user1672591    9 年前

    我的解决方案:

    // 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;
    };
    
        17
  •  0
  •   Community pid    7 年前

    在我的例子中,表单的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;
        };
    
        18
  •  0
  •   Dani    7 年前

    更改提交按钮:

    <input id="submitButtonId" type="submit" value="Delete" />
    

    带普通按钮:

    <input id="submitButtonId" type="button" value="Delete" />
    

    然后使用单击功能:

    $("#submitButtonId").click(function () {
            $('#submitButtonId').prop('disabled', true);
            $('#myForm').submit();
        });
    

    $('#submitButtonId').prop('disabled', false);
    
        19
  •  0
  •   Tom McDonough    6 年前

    $(document).on('click', '#SubmitButton', function () {
        $(this).css('pointer-events', 'none');
    })
    
        20
  •  0
  •   gene b.    5 年前

    为什么不这样做呢--这会提交表单,但也会禁用提交按钮,

       $('#myForm').on('submit', function(e) {
           var clickedSubmit = $(this).find('input[type=submit]:focus');
           $(clickedSubmit).prop('disabled', true);
       });
    

    另外,如果使用jQuery Validate,可以将这两行放在 if ($('#myForm').valid()) .

        21
  •  0
  •   Dharman Aman Gojariya    4 年前

    此代码将在按钮标签上显示加载,并将按钮设置为

    禁用状态,然后在处理之后,重新启用并返回原始按钮文本**

    $(function () {
    
        $(".btn-Loading").each(function (idx, elm) {
            $(elm).click(function () {
                //do processing
                if ($(".input-validation-error").length > 0)
                    return;
                $(this).attr("label", $(this).text()).text("loading ....");
                $(this).delay(1000).animate({ disabled: true }, 1000, function () {
                    //original event call
                    $.when($(elm).delay(1000).one("click")).done(function () {
                        $(this).animate({ disabled: false }, 1000, function () {
                            $(this).text($(this).attr("label"));
                        })
                    });
                    //processing finalized
                });
            });
        });
        // and fire it after definition
    });
    
        22
  •  -1
  •   Nolan    13 年前

    $("#my_form").submit(function(){
        $('input[type=submit]').click(function(event){
            event.preventDefault();
        });
    });