天道酬勤,学无止境

Prevent double submission of forms in jQuery

Question

I have a form that takes a little while for the server to process. I need to ensure that the user waits and does not attempt to resubmit the form by clicking the button again. I tried using the following jQuery code:

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

When I try this in Firefox everything gets disabled but the form is not submitted with any of the POST data it is supposed to include. I can't use jQuery to submit the form because I need the button to be submitted with the form as there are multiple submit buttons and I determine which was used by which one's value is included in the POST. I need the form to be submitted as it usually is and I need to disable everything right after that happens.

Thanks!

Answer1

Update in 2018: I just got some points for this old answer, and just wanted to add that the best solution would be to make the operation idempotent so that duplicate submissions are harmless.

Eg, if the form creates an order, put a unique ID in the form. The first time the server sees an order creation request with that id, it should create it and respond "success". Subsequent submissions should also respond "success" (in case the client didn't get the first response) but shouldn't change anything.

Duplicates should be detected via a uniqueness check in the database to prevent race conditions.


I think that your problem is this line:

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

You're disabling ALL the inputs, including, I'd guess, the ones whose data the form is supposed to submit.

To disable just the submit button(s), you could do this:

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

However, I don't think IE will submit the form if even those buttons are disabled. I'd suggest a different approach.

A jQuery plugin to solve it

We just solved this problem with the following code. The trick here is using jQuery's data() to mark the form as already submitted or not. That way, we don't have to mess with the submit buttons, which freaks IE out.

// 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;
};

Use it like this:

$('form').preventDoubleSubmission();

If there are AJAX forms that should be allowed to submit multiple times per page load, you can give them a class indicating that, then exclude them from your selector like this:

$('form:not(.js-allow-double-submission)').preventDoubleSubmission();
Answer2

Timing approach is wrong - how do you know how long the action will take on client's browser?

How to do it

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

When form is submitted it will disable all submit buttons inside.

Remember, in Firefox when you disable a button this state will be remembered when you go back in history. To prevent that you have to enable buttons on page load, for example.

Answer3

I think Nathan Long's answer is the way to go. For me, I am using client-side validation, so I just added a condition that the form be valid.

EDIT: If this is not added, the user will never be able to submit the form if the client-side validation encounters an error.

        // 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;
        };
Answer4

event.timeStamp doesn't work in Firefox. Returning false is non-standard, you should call event.preventDefault(). And while we're at it, always use braces with a control construct.

To sum up all of the previous answers, here is a plugin that does the job and works cross-browser.

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;
    });
};

To address Kern3l, the timing method works for me simply because we're trying to stop a double-click of the submit button. If you have a very long response time to a submission, I recommend replacing the submit button or form with a spinner.

Completely blocking subsequent submissions of the form, as most of the above examples do, has one bad side-effect: if there is a network failure and they want to try to resubmit, they would be unable to do so and would lose the changes they made. This would definitely make an angry user.

Answer5

Please, check out jquery-safeform plugin.

Usage example:

$('.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;
    }
});
Answer6

...but the form is not submitted with any of the POST data it is supposed to include.

Correct. Disabled form element names/values will not be sent to the server. You should set them as readonly elements.

Also, anchors cannot be disabled like that. You will need to either remove their HREFs (not recommended) or prevent their default behaviour (better way), e.g.:

<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>
Answer7

There is a possibility to improve Nathan Long's approach. You can replace the logic for detection of already submitted form with this one:

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
Answer8

Nathan's code but for jQuery Validate plugin

If you happen to use jQuery Validate plugin, they already have submit handler implemented, and in that case there is no reason to implement more than one. The code:

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;
    }
  }
});

You can easily expand it within the } else {-block to disable inputs and/or submit button.

Cheers

Answer9

I ended up using ideas from this post to come up with a solution that is pretty similar to AtZako's version.

 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;
  });   
};

Using like this:

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

I found that the solutions that didn't include some kind of timeout but just disabled submission or disabled form elements caused problems because once the lock-out is triggered you can't submit again until you refresh the page. That causes some problems for me when doing ajax stuff.

This can probably be prettied up a bit as its not that fancy.

Answer10

If using AJAX to post a form, set async: false should prevent additional submits before the form clears:

$("#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;
   }
});
Answer11

Modified Nathan's solution a little for Bootstrap 3. This will set a loading text to the submit button. In addition it will timeout after 30 seconds and allow the form to be resubmitted.

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);
};
Answer12

Use two submit buttons.

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

And jQuery:

$("#sub").click(function(){
  $(this).val("Please wait..");
  $(this).attr("disabled","disabled");
  $("#sub2").click();
});
Answer13

Use simple counter on submit.

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

And call monitor() function on submit the form.

    <form action="/someAction.go" onsubmit="return monitor();" method="POST">
        ....
        <input type="submit" value="Save Data">
    </form>
Answer14

I've been having similar issues and my solution(s) are as follows.

If you don't have any client side validation then you can simply use the jquery one() method as documented here.

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

This disables the handler after its been invoked.

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

If you're doing client side validation as I was doing then its slightly more tricky. The above example would not let you submit again after failed validation. Try this approach instead

$("#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);
   }
});
Answer15

You can stop the second submit by this

$("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
    });
});
Answer16

My solution:

// 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;
};
Answer17

In my case the form's onsubmit had some validation code, so I increment Nathan Long answer including an onsubmit checkpoint

$.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;
    };
Answer18

Change submit button:

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

With normal button:

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

Then use click function:

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

And remember re-enable button when is necesary:

$('#submitButtonId').prop('disabled', false);
Answer19

I can't believe the good old fashioned css trick of pointer-events: none hasn't been mentioned yet. I had the same issue by adding a disabled attribute but this doesn't post back. Try the below and replace #SubmitButton with the ID of your submit button.

$(document).on('click', '#SubmitButton', function () {
    $(this).css('pointer-events', 'none');
})
Answer20

Why not just this -- this will submit the form but also disable the submitting button,

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

Also, if you're using jQuery Validate, you can put these two lines under if ($('#myForm').valid()).

Answer21

this code will display loading on the button label, and set button to

disable state, then after processing, re-enable and return back the original button text**

$(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
});
Answer22

I solved a very similar issue using:

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

Restricted HTML

  • Allowed HTML tags: <a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • Lines and paragraphs break automatically.
  • Web page addresses and email addresses turn into links automatically.

相关推荐
  • How to prevent form from being submitted?
    Question I have a form that has a submit button in it somewhere. However, I would like to somehow 'catch' the submit event and prevent it from occurring. Is there some way I can do this? I can't modify the submit button, because it's part of a custom control. Answer1 Unlike the other answers, return false is only part of the answer. Consider the scenario in which a JS error occurs prior to the return statement... html <form onsubmit="return mySubmitFunction(event)"> ... </form> script function mySubmitFunction() { someBug() return false; } returning false here won't be executed and the form
  • Preventing form resubmission
    Question Page one contains an HTML form. Page two - the code that handles the submitted data. The form in page one gets submitted. The browser gets redirected to page two. Page two handles the submitted data. At this point, if page two gets refreshed, a "Confirm Form Resubmission" alert pops up. Can this be prevented? Answer1 There are 2 approaches people used to take here: Method 1: Use AJAX + Redirect This way you post your form in the background using JQuery or something similar to Page2, while the user still sees page1 displayed. Upon successful posting, you redirect the browser to Page2
  • How to prevent robots from automatically filling up a form?
    Question I'm trying to come up with a good enough anti-spamming mechanism to prevent automatically generated input. I've read that techniques like captcha, 1+1=? stuff work well, but they also present an extra step impeding the free quick use of the application (I'm not looking for anything like that please). I've tried setting some hidden fields in all of my forms, with display: none; However, I'm certain a script can be configured to trace that form field id and simply not fill it. Do you implement/know of a good anti automatic-form-filling-robots method? Is there something that can be done
  • How do I cancel form submission in submit button onclick event?
    Question I'm working on an ASP.net web application. I have a form with a submit button. The code for the submit button looks like <input type='submit' value='submit request' onclick='btnClick();'>. I want to write something like the following: function btnClick() { if (!validData()) cancelFormSubmission(); } How do I do this? Answer1 You are better off doing... <form onsubmit="return isValidForm()" /> If isValidForm() returns false, then your form doesn't submit. You should also probably move your event handler from inline. document.getElementById('my-form').onsubmit = function() { return
  • How to prevent form resubmission when page is refreshed (F5 / CTRL+R)
    Question I have a simple form that submits text to my SQL table. The problem is that after the user submits the text, they can refresh the page and the data gets submitted again without filling the form again. I could redirect the user to another page after the text is submitted, but I want users to stay on the same page. I remember reading something about giving each user a unique session id and comparing it with another value which solved the problem I am having but I forgot where it is. Answer1 Use the Post/Redirect/Get pattern. http://en.wikipedia.org/wiki/Post/Redirect/Get With my website
  • Prevent users from submitting a form by hitting Enter
    Question I have a survey on a website, and there seems to be some issues with the users hitting enter (I don't know why) and accidentally submitting the survey (form) without clicking the submit button. Is there a way to prevent this? I'm using HTML, PHP 5.2.9, and jQuery on the survey. Answer1 You can use a method such as $(document).ready(function() { $(window).keydown(function(event){ if(event.keyCode == 13) { event.preventDefault(); return false; } }); }); In reading the comments on the original post, to make it more usable and allow people to press Enter if they have completed all the
  • jQuery Ajax POST example with PHP
    Question I am trying to send data from a form to a database. Here is the form I am using: <form name="foo" action="form.php" method="POST" id="foo"> <label for="bar">A bar</label> <input id="bar" name="bar" type="text" value="" /> <input type="submit" value="Send" /> </form> The typical approach would be to submit the form, but this causes the browser to redirect. Using jQuery and Ajax, is it possible to capture all of the form's data and submit it to a PHP script (an example, form.php)? Answer1 Basic usage of .ajax would look something like this: HTML: <form id="foo"> <label for="bar">A bar<
  • JavaScript code to stop form submission
    Question One way to stop form submission is to return false from your JavaScript function. When the submit button is clicked, a validation function is called. I have a case in form validation. If that condition is met I call a function named returnToPreviousPage(); function returnToPreviousPage() { window.history.back(); } I am using JavaScript and Dojo Toolkit. Rather going back to the previous page, it submits the form. How can I abort this submission and return to the previous page? Answer1 You can use the return value of the function to prevent the form submission <form name="myForm"
  • Prevent any form of page refresh using jQuery/Javascript
    Question Once the user is on my page, I do not want him to refresh the page. Anytime, the user hits F5 or refresh button on top. He should get an alert saying You cannot refresh the page. Also if the user opens a new tab and tries to access the same url in prev tab he should get an alert You cannot open same page in 2 tabs Anyway I can do this using JavaScript or jQuery? Point one is really important. Answer1 #1 can be implemented via window.onbeforeunload. For example: <script type="text/javascript"> window.onbeforeunload = function() { return "Dude, are you sure you want to leave? Think of
  • Keep values selected after form submission
    Question Consider: <form method="get" action=""> <select name="name"> <option value="a">a</option> <option value="b">b</option> </select> <select name="location"> <option value="x">x</option> <option value="y">y</option> </select> <input type="submit" value="Submit" class="submit" /> </form> On submitting the form, how do I make sure that the selected values remain selected in the dropdowns? This form is inside WordPress (PHP). Answer1 To avoid many if-else structures, let JavaScript do the trick automatically: <select name="name" id="name"> <option value="a">a</option> <option value="b">b<
  • POST data in JSON format
    Question I have some data that I need to convert to JSON format and then POST it with a JavaScript function. <body onload="javascript:document.myform.submit()"> <form action="https://www.test.net/Services/RegistrationService.svc/InviteNewContact" method="post" name="myform"> <input name="firstName" value="harry" /> <input name="lastName" value="tester" /> <input name="toEmail" value="testtest@test.com" /> </form> </body> This is the way the post looks now. I need it submit the values in JSON format and do the POST with JavaScript. Answer1 Not sure if you want jQuery. var form; form.onsubmit =
  • [pthon2.7+django1.2+sae] Asynchronous submission of blog comments
    In the development of a blog system or an e-commerce system, in short, when there is a response to a content such as replies, comments, and replies, almost all of them are submitted asynchronously by ajax, and the submission is displayed in the correct position synchronously. As a result, instead of refreshing the entire page after submission to display the content after submission. Ajax is widely promoted due to the use of google. It is written in javascript on the client and uses the XMLHttpRequest object to realize data interaction with the service. For details, see: AJAX-XMLHttpRequest
  • jQuery UI modal form crazy stepping on the pit
    Want to apply the front-end components to write a form validation page, so I tried jQuery UI Examples of official websites First paste the example from the official website: <!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>jQuery UI Dialog - Modal form</title> <link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css"> <link rel="stylesheet" href="/resources/demos/style.css"> <style> label, input { display:block; } input.text { margin-bottom:12px; width:95%; padding: .4em; }
  • Prevent form redirect OR refresh on submit?
    Question I've searched through a bunch of pages, but can't find my problem, so I had to make a post. I have a form that has a submit button, and when submitted I want it to NOT refresh OR redirect. I just want jQuery to perform a function. Here's the form: <form id="contactForm"> <fieldset> <label for="Name">Name</label> <input id="contactName" type="text" /> </fieldset> <fieldset> <label for="Email">Email</label> <input id="contactEmail" type="text" /> </fieldset> <fieldset class="noHeight"> <textarea id="contactMessage" cols="20"></textarea> <input id="contactSend" class="submit" type=
  • Layer form validation and submission
    1. Layer form submission and verification method (add employee page)<form class="layui-form layui-form-pane1 pzjzsj" action=""> <div class="layui-form-item"> <label class="layui-form-label">手机号</label> <div class="layui-input-inline"> <input type="text" name="mobile" lay-verify="phone" placeholder="请输入手机号" autocomplete="off" class="layui-input" value="${PhomeUser.mobile }"/> </div> </div> <div class="layui-form-item"><label class="layui-form-label">Real name</label> <div class="layui-input-inline"> <input type="text" name="truename" lay-verify="required" placeholder="请输入姓名" autocomplete="off"
  • php $_POST array empty upon form submission
    Question I have a custom Content Management System (CMS) I've built that works perfectly on my dev box (Ubuntu/PHP5+/MySQL5+). I just moved it up to the production box for my client and now all form submissions are showing up as empty $_POST arrays. I found a trick to verify the data is actually being passed using file_get_contents('php://input'); and the data is showing up fine there -- the $_POST/$_REQUEST arrays are always empty. I've also verified the content-type headers are correct as well via firebug (application/x-www-form-urlencoded; charset=utf-8). This issue is happening regardless
  • How to prevent buttons from submitting forms
    Question In the following page, with Firefox the remove button submits the form, but the add button does not. How do I prevent the remove button from submitting the form? function addItem() { var v = $('form :hidden:last').attr('name'); var n = /(.*)input/.exec(v); var newPrefix; if (n[1].length == 0) { newPrefix = '1'; } else { newPrefix = parseInt(n[1]) + 1; } var oldElem = $('form tr:last'); var newElem = oldElem.clone(true); var lastHidden = $('form :hidden:last'); lastHidden.val(newPrefix); var pat = '=\"' + n[1] + 'input'; newElem.html(newElem.html().replace(new RegExp(pat, 'g'), '=\"' +
  • How do I remove a file from the FileList
    Question I'm building a drag-and-drop-to-upload web application using HTML5, and I'm dropping the files onto a div and of course fetching the dataTransfer object, which gives me the FileList. Now I want to remove some of the files, but I don't know how, or if it's even possible. Preferably I'd like to just delete them from the FileList; I've got no use for them. But if that's not possible, should I instead write in checks in code that interacts with the FileList? That seems cumbersome. Answer1 If you want to delete only several of the selected files: you can't. The File API Working Draft you
  • jQuery ajax upload file in asp.net mvc
    Question I have a file in my view <form id="upload" enctype="multipart/form-data"> <input type="file" name="fileUpload" id="fileUpload" size="23" /> </form> and an ajax request $.ajax({ url: '<%=Url.Action("JsonSave","Survey") %>', dataType: 'json', processData: false, contentType: "multipart/mixed", data: { Id: selectedRow.Id, Value: 'some date was added by the user here :))' }, cache: false, success: function (data) {} }); but there is no file in the Request.Files. Whats wrong with the ajax request? Answer1 Upload files using AJAX in ASP.Net MVC Things have changed since HTML5 JavaScript