117

Sometimes when the response is slow, one might click the submit button multiple times.

How to prevent this from happening?

Dan Homola
  • 3,819
  • 1
  • 28
  • 43
omg
  • 136,412
  • 142
  • 288
  • 348
  • 4
    I hope the reason you put "client side" on your question title is because you are aware that any solution on the client to try and avoid dupe submissions is 100% insecure and you should _always_ do validation on the server side. – Paolo Bergantino May 29 '09 at 22:44
  • 59
    Paolo: Yes, if you're interested complete data security it should be done server-side. But sometimes you just want to prevent grandma from double-clicking the submit button when it only needs a single click. In these cases javascript is perfectly fine. – Simon East Sep 07 '11 at 01:57
  • 2
    Doing it only server-side is not 100% safe as well, since your first request might take long enough to finish so the second one would know it should not proceed. – igorsantos07 Mar 06 '15 at 00:18
  • Doesn't the [Double-Submit Cookie Pattern](https://medium.com/@dinuksha.ishwari/preventing-cross-site-request-forgery-using-double-submit-cookie-pattern-f1436274c7cc) to prevent CSRF attacks also prevent mutliple form submission? – Martin Thoma Jun 12 '19 at 05:44

25 Answers25

109

Use unobtrusive javascript to disable the submit event on the form after it has already been submitted. Here is an example using jQuery.

EDIT: Fixed issue with submitting a form without clicking the submit button. Thanks, ichiban.

$("body").on("submit", "form", function() {
    $(this).submit(function() {
        return false;
    });
    return true;
});
Starx
  • 77,474
  • 47
  • 185
  • 261
  • 5
    What if the form is submitted by pressing enter in a textbox? – ichiban May 29 '09 at 16:18
  • 2
    Do you even need the `return true`? I think the initial submit should work without that. – Simon East Sep 07 '11 at 02:16
  • I believe the `return true` is implied if omitted. – Derek Feb 10 '12 at 17:26
  • 17
    I tried this solution with unobtrusive validation & MVC. The JS gets called first which always return false and then validation is called. So if my form has some validation error the form never gets submitted!! – bjan Jun 08 '12 at 12:09
  • 7
    works really great. i also like to disable the submit button and replace the submit button text to show user hint as well. `$(this).find("input[type='submit']").attr('disabled', 'disabled').val('submiting'); return true; });` – Cam Song Apr 07 '13 at 15:34
  • @ichiban An easy way to deal with this is to disable form submission through the enter key. An inline way is as follows - either disable the use of the enter key all fields in a form by adding this to the form tag `onkeypress="return event.keyCode != 13;"` or add the same inline code directly to an input element tag which will still allow you to use the enter key in a textarea element where the first option might pose a problem. – andromeda Oct 08 '16 at 12:11
  • Use `$(this).find(':submit').prop('disabled', true)` as a shortcut and also find bootstrap's ` – vault Feb 27 '17 at 11:56
  • Darling your the beeaast <3 – ii iml0sto1 May 04 '20 at 14:58
47

I tried vanstee's solution along with asp mvc 3 unobtrusive validation, and if client validation fails, code is still run, and form submit is disabled for good. I'm not able to resubmit after correcting fields. (see bjan's comment)

So I modified vanstee's script like this:

$("form").submit(function () {
    if ($(this).valid()) {
        $(this).submit(function () {
            return false;
        });
        return true;
    }
    else {
        return false;
    }
});
Martin
  • 22,212
  • 11
  • 70
  • 132
m irina
  • 471
  • 4
  • 3
24

Client side form submission control can be achieved quite elegantly by having the onsubmit handler hide the submit button and replace it with a loading animation. That way the user gets immediate visual feedback in the same spot where his action (the click) happened. At the same time you prevent the form from being submitted another time.

If you submit the form via XHR keep in mind that you also have to handle submission errors, for example a timeout. You would have to display the submit button again because the user needs to resubmit the form.

On another note, llimllib brings up a very valid point. All form validation must happen server side. This includes multiple submission checks. Never trust the client! This is not only a case if javascript is disabled. You must keep in mind that all client side code can be modified. It is somewhat difficult to imagine but the html/javascript talking to your server is not necessarily the html/javascript you have written.

As llimllib suggests, generate the form with an identifier that is unique for that form and put it in a hidden input field. Store that identifier. When receiving form data only process it when the identifier matches. (Also linking the identifier to the users session and match that, as well, for extra security.) After the data processing delete the identifier.

Of course, once in a while, you'd need to clean up the identifiers for which never any form data was submitted. But most probably your website already employs some sort of "garbage collection" mechanism.

Rob
  • 489
  • 2
  • 6
17

Here's simple way to do that:

<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>
ichiban
  • 6,162
  • 3
  • 27
  • 34
  • 1
    with jQuery unobtrusive validation, the blocking script gets called first and validation next which results no submission at all if there are validation errors – bjan Jun 08 '12 at 12:30
16
<form onsubmit="if(submitted) return false; submitted = true; return true">
chaos
  • 122,029
  • 33
  • 303
  • 309
  • 8
    Use `
    `, or write `var submitted = false;` at the right point of your script, to avoid the following error: `Uncaught ReferenceError: submitted is not defined`.
    – Tamás Bolvári Nov 21 '14 at 14:38
10

The most simple answer to this question as asked: "Sometimes when the response is slow, one might click the submit button multiple times. How to prevent this from happening?"

Just Disable the form submit button, like below code.

<form ... onsubmit="buttonName.disabled=true; return true;">
  <input type="submit" name="buttonName" value="Submit">
</form>

It will disable the submit button, on first click for submitting. Also if you have some validation rules, then it will works fine. Hope it will help.

Imran Khan
  • 2,373
  • 2
  • 22
  • 35
9

Create a unique identifier (for example, you can hash the current time), and make it a hidden input on the form. On the server side, check the unique identifier of each form submission; if you've already received that hash then you've got a repeat submission. The only way for the user to re-submit is to reload the form page.

edit: relying on javascript is not a good idea, so you all can keep upvoting those ideas but some users won't have it enabled. The correct answer is to not trust user input on the server side.

Ben Davis
  • 13,112
  • 10
  • 50
  • 65
llimllib
  • 3,642
  • 1
  • 29
  • 29
  • Dont this look "Too much"? ;-) – Shoban May 29 '09 at 16:12
  • 1
    That sounds like it would just keep a user from submitting the form more than once per second. If I submit the form at 2009-05-29 12:13:37, then the server won't let me submit another form with that same hash, but if I clicked Submit at 2009-05-29 12:13:38, it would go through. Also, your technique would prevent 2 different users from simultaneously submitting two different forms: one of them would be kicked out, even though it would be possibly the first submission from him. – Sarah Vessels May 29 '09 at 16:14
  • 2
    @moneypenny your first objection is false, the hash would be of the time the form was sent to the user, not the time they submit. If you're truly worried about the second, you have plenty of options. Add their session ID to the string you hash, and/or check all fields of the form for exact sameness; two users probably didn't submit exactly the same form. – llimllib May 29 '09 at 16:16
  • @Shoban I'm sorry, I don't follow what you're saying – llimllib May 29 '09 at 16:17
  • I suppose you could use micro-time. Seems dirty though. – Aiden Bell May 29 '09 at 16:18
  • how does it "seem dirty"? It seems like a simple, elegant solution to me. – llimllib May 29 '09 at 16:20
  • This would require you to store a table of hashed forms somewhere or to add a column to whatever table you're presumably inserting to for the hash. This solution seems excessive to me. – Matt Brunmeier May 29 '09 at 16:32
  • 3
    "Excessive" is in the eye of the beholder. If you *really* need to prevent duplicate form submissions, at least part of the solution has to be server-side. "You can't trust users." – Ben Blank May 29 '09 at 22:32
  • I like this idea. However, how about using actual datetime instead of a hashed value? That way you can check if it's the same to prevent duplicates as above. Also, you can check it's a valid datetime which might prevent direct robot submissions (that don't use the original form page). Thirdly, you probably already have a datetime field for the submission so it doesn't add a new column to your table. Ah, checking more, MySQL, doesn't save fractional seconds w/ DATETIMEs. Just using that might prevent submissions from 2 different people that actually loaded the form at the same time. – Michael K Dec 30 '11 at 16:16
  • 1
    Everyone seems to be misunderstanding the use of timestamp hash in this solution. The point of the timestamp hash is to get a UNIQUE IDENTIFIER, not the time. The unique id identifies the form instance, which should be submitted only once. If that id is submitted twice, it's marked as a duplicate. If the user wants to re-submit, they have to re-load the form. – Ben Davis Nov 18 '21 at 17:04
8

Disable the submit button soon after a click. Make sure you handle validations properly. Also keep an intermediate page for all processing or DB operations and then redirect to next page. THis makes sure that Refreshing the second page does not do another processing.

Shoban
  • 22,920
  • 8
  • 63
  • 107
  • Yeah, great tip Shoban, I agree. Should be `form page ---submits to---> form_submission_script.php ---after saving, redirects to---> form_thankyou.html` – Simon East Sep 07 '11 at 02:18
5

You could also display a progress bar or a spinner to indicate that the form is processing.

Tony Borf
  • 4,579
  • 8
  • 43
  • 51
5

Using JQuery you can do:

$('input:submit').click( function() { this.disabled = true } );

&

   $('input:submit').keypress( function(e) {
     if (e.which == 13) {
        this.disabled = true 
     } 
    }
   );
Boris Guéry
  • 47,316
  • 8
  • 52
  • 87
  • 1
    What if the form is submitted by pressing ENTER in a textbox after the button is disabled? – ichiban May 29 '09 at 16:20
  • Disabling the button like this will prevent the user to press ENTER then. But, right it needs to bind a keypress on the submit input – Boris Guéry May 29 '09 at 16:23
  • This prevents the button to submit. Hence, disabling server side validation. – Marko Aleksić Mar 26 '11 at 13:50
  • @Marko, right, but that's the OP asked for, anyway use a token would prevent the form to submit twice. – Boris Guéry Mar 26 '11 at 16:33
  • 1
    When I tried this kind of technique, I found that the form would not submit at all (at least not in Chrome 14), presumably because you disable the button before the browser starts the form submission. – Simon East Sep 07 '11 at 02:22
4

You can prevent multiple submit simply with :

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;

});
Alpha
  • 455
  • 1
  • 5
  • 16
  • The problem with your answer is that there's a split second between the time the user clicks and the time `Workin =true;`. Double submits are still possible, but fewer are likely. – sent1nel Feb 07 '14 at 23:44
4

On the client side, you should disable the submit button once the form is submitted with javascript code like as the method provided by @vanstee and @chaos.

But there is a problem for network lag or javascript-disabled situation where you shouldn't rely on the JS to prevent this from happening.

So, on the server-side, you should check the repeated submission from the same clients and omit the repeated one which seems a false attempt from the user.

steveyang
  • 9,178
  • 8
  • 54
  • 80
  • I know this was answered a long time ago but can someone explain how network lag might prevent the disable? I'm dealing with this issue right now and I am very confused as to how a form was double-submitted even though I disable the button. I never even thought about JavaScript disabled. I don't think that's the issue in my case, but it is interesting insight nonetheless. – davidatthepark Aug 19 '19 at 20:56
  • I was also considering throttling the click handler. – davidatthepark Aug 19 '19 at 21:07
  • How would you check server side if submission from same client? By user IP address? If so, where would you "save" the IP address server-side from a previously submitted entry? (i'm using node if that context is required) – user1063287 Sep 05 '20 at 12:06
4

I know you tagged your question with 'javascript' but here's a solution that do not depends on javascript at all:

It's a webapp pattern named PRG, and here's a good article that describes it

Pablo Fernandez
  • 103,170
  • 56
  • 192
  • 232
3

You can try safeform jquery plugin.

$('#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;
    }
})
Max Kamenkov
  • 2,478
  • 3
  • 22
  • 19
1

The simpliest and elegant solution for me:

function checkForm(form) // Submit button clicked
{
    form.myButton.disabled = true;
    form.myButton.value = "Please wait...";
    return true;
}

<form method="POST" action="..." onsubmit="return checkForm(this);">
    ...
    <input type="submit" name="myButton" value="Submit">
</form>

Link for more...

Solis
  • 11
  • 2
1

Use this code in your form.it will handle multiple clicks.

<script type="text/javascript">
    $(document).ready(function() {
        $("form").submit(function() {
            $(this).submit(function() {
                return false;
            });
            return true;
        });     
    }); 
</script>

it will work for sure.

Kalamarico
  • 5,466
  • 22
  • 53
  • 70
Bachas
  • 233
  • 6
  • 16
1

This allow submit every 2 seconds. In case of front validation.

$(document).ready(function() {
    $('form[debounce]').submit(function(e) {
        const submiting = !!$(this).data('submiting');

        if(!submiting) {
            $(this).data('submiting', true);

            setTimeout(() => {
                $(this).data('submiting', false);
            }, 2000);

            return true;
        }

        e.preventDefault();
        return false;
    });
})
Aurel
  • 3,682
  • 1
  • 19
  • 22
0

the best way to prevent multiple from submission is this just pass the button id in the method.

    function DisableButton() {
        document.getElementById("btnPostJob").disabled = true;
    }
    window.onbeforeunload = DisableButton; 
0

To do this using javascript is bit easy. Following is the code which will give desired functionality :

$('#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>
Rish
  • 1,303
  • 9
  • 22
0

Most simple solutions is that disable the button on click, enable it after the operation completes. To check similar solution on jsfiddle :

[click here][1]

And you can find some other solution on this answer.

Community
  • 1
  • 1
Kalyani
  • 391
  • 3
  • 5
  • 1
    While a link is great, please [provide context to your link(s)](http://meta.stackoverflow.com/a/8259/169503), as an *answer* should actually contain an answer. Be aware that being *barely more than a link to an external site* is a possible reason as to [Why and how are some answers deleted?](http://stackoverflow.com/help/deleted-answers). – Jan Mar 08 '17 at 07:28
0

This works very fine for me. It submit the farm and make button disable and after 2 sec active the button.

<button id="submit" type="submit" onclick="submitLimit()">Yes</button>

function submitLimit() {
var btn = document.getElementById('submit')
setTimeout(function() {
    btn.setAttribute('disabled', 'disabled');
}, 1);

setTimeout(function() {
    btn.removeAttribute('disabled');
}, 2000);}

In ECMA6 Syntex

function submitLimit() {
submitBtn = document.getElementById('submit');

setTimeout(() => { submitBtn.setAttribute('disabled', 'disabled') }, 1);

setTimeout(() => { submitBtn.removeAttribute('disabled') }, 4000);}
Awais Jameel
  • 1,838
  • 19
  • 14
0

Just to add to the possible answers without bypassing browser input validation

$( document ).ready(function() {
    $('.btn-submit').on('click', function() {
        if(this.form.checkValidity()) {
            $(this).attr("disabled", "disabled");
            $(this).val("Submitting...");
            this.form.submit();
        }
    });
});
Roi
  • 503
  • 1
  • 12
  • 25
0

An alternative to what was proposed before is:

jQuery('form').submit(function(){
     $(this).find(':submit').attr( 'disabled','disabled' );
     //the rest of your code
});
0
<h3>Form</h3>
<form action='' id='theform' >
<div class='row'>
    <div class="form-group col-md-4">
            <label for="name">Name:</label>
            <input type='text' name='name' class='form-control'/>
    </div>
</div>  
<div class='row'>
    <div class="form-group col-md-4">
            <label for="email">Email:</label>
            <input type='text' name='email' class='form-control'/>
    </div>
</div>  
<div class='row'>
    <div class="form-group col-md-4">
         <input class='btn btn-primary pull-right' type="button" value="Submit" id='btnsubmit' />   
    </div>
</div>
</form>



<script>

    $(function()
    {
      $('#btnsubmit').on('click',function()
      {
        $(this).val('Please wait ...')
          .attr('disabled','disabled');
        $('#theform').submit();
      });
      
    });

</script>
danish_wani
  • 862
  • 9
  • 14
0

This is a clean Javascript code that prevents multiple valid submissions:

<script>
var form = document.querySelector('form');
form.onsubmit = function(e){
    if(form.reportValidity())
        // if form is valid, prevent future submissions by returning false.
        form.onsubmit = (e)=> false;
    return true;
}
</script>
Omar Lajam
  • 31
  • 5