20

I keep getting duplicate entries in my database because of impatient users clicking the submit button multiple times.

I googled and googled and found a few scripts, but none of them seem to be sufficient.

How can I prevent these duplicate entries from occurring using javascript or preferably jQuery?

Thanx in advance!

Nikola Petkanski
  • 4,724
  • 1
  • 33
  • 41
Odyss3us
  • 6,457
  • 18
  • 74
  • 112

11 Answers11

31

How about disabling the button on submit? That's what I do. It works fine.

$('form').submit(function(){
    $('input[type=submit]', this).attr('disabled', 'disabled');
});

Disclaimer:
This only works when javascript is enabled on the user's browser. If the data that's being submitted is critical (like a credit card purchase), then consider my solution as only the first line of defense. For many use cases though, disabling the submit button will provide enough prevention.

I would implement this javascript-only solution first. Then track how many duplicate records are still getting created. If it's zero (or low enough to not care), then you're done. If it's too high for you, then implement a back-end database check for an existing record.

Bill Paetzke
  • 13,332
  • 6
  • 44
  • 46
  • 2
    Javascript is only part of the solution here, you should be checking the database as well to check if data has just been entered. If you have a unique piece of data you can check this is the best way, but another method is to have a timestamp on the data and check if that user has added anything in a short period of time. However this would depend on the application on what it is that you are adding. – dnolan Apr 14 '10 at 07:57
  • I do have a unique piece of data that I can check, each id_number is unique, how would I go about implementing a check like that? – Odyss3us Apr 14 '10 at 08:45
  • @kielie is id_number an identity field? – dnolan Apr 14 '10 at 10:37
  • No it isn't, it's a normal field entered by the user, but each one is unique. – Odyss3us Apr 14 '10 at 15:05
  • @kielie in that case, you should do a quick select prior to your insert to see if that unique id already exists, if so, return an message to the user to cease being an impatient so and so – dnolan Apr 14 '10 at 19:52
  • A word of caution. The problem with the "database check for an existing record" is that many web frameworks (such as Django) by default handle a request as a single transaction, and don't commit until the response is given. So, depending on your transaction isolation level, you can still have a write to the db that just has not been committed and therefore is not visible to the second request. Therefore, the check fails. – David S Sep 26 '13 at 21:44
  • 2
    Bad solution if form value is important. Only not disabled fields will be sent. Disabled fields (buttons) will be not sent with form. In this case use this variant ` var isFormSubmitted = false; form.submit(function(){ if(isFormSubmitted){ return false; } //if form valid disable submitted form to prevent a double submit isFormSubmitted = true; }); ` – Bohdan Lyzanets Oct 29 '13 at 16:44
  • This solution is not applicable for applications that have client-side validation – Gabe Jun 21 '21 at 21:32
9

This should do the trick:

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

No JQuery?

Alternatively, you can make a check from db to check if a record already exist and if so, don't insert new one.

Sarfraz
  • 377,238
  • 77
  • 533
  • 578
  • I do have a unique piece of data that I can check, each id_number is unique, how would I go about implementing a check like that? – Odyss3us Apr 14 '10 at 09:10
8

Preventing the double posting is not so simple as disabling the submit button. There are other elements that may submit it:

  • button elements
  • img elements
  • javascripts
  • pressing 'enter' while on some text field

Using jQuery data container would be my choice. Here's an example:

$('#someForm').submit(function(){
    $this = $(this);

    /** prevent double posting */
    if ($this.data().isSubmitted) {
        return false;
    }

    /** do some processing */

    /** mark the form as processed, so we will not process it again */
    $this.data().isSubmitted = true;

    return true;
});
Nikola Petkanski
  • 4,724
  • 1
  • 33
  • 41
7

One technique I've seen used is to assign a unique ID to every form that's opened, and only accept one submission per form based on the ID.

It also means you can check how many times people aren't bothering to submit at all, and you can check if the submission genuinely came from your form by checking if it's got an ID that your server created.

I know you asked for a javascript solution, but personally I'd do both if I needed the robustness.

Flynn1179
  • 11,925
  • 6
  • 38
  • 74
  • For mission-critical applications that involve the transfer of money, this is really the best way to do it. – Simon East May 07 '13 at 02:29
2

Here is bit of jQuery that I use to avoid the double click problem. It will only allow one click of the submit button.

$(document).ready(function() {
  $("#submit").on('click', function() {
  });
});
Muleskinner
  • 14,150
  • 19
  • 58
  • 79
Jim Schmehil
  • 6,881
  • 2
  • 15
  • 6
  • This is good but what if some sort of validation in the form fails, then the form has to be reloaded, right? – nulltek May 22 '16 at 17:23
1

I'm not sure what language/framework you're working with or if it's just straight HTML. But in a Rails app I wrote I pass a data attribute on the form button disable_with which keeps the button from being clickable more than once while the transaction is in process.

Here's what the ERB looks like.

<%= f.button "Log In", class: 'btn btn-large btn-block btn-primary', data: {disable_with: "<i class='icon-spinner'></i>Logging In..."} %>
nulltek
  • 3,247
  • 9
  • 44
  • 94
1

This is what I came up with in https://github.com/liberapay/liberapay.com/pull/875:

$('form').on('submit', function (e) {
    var $form = $(this);
    // Check that the form hasn't already been submitted
    if ($form.data('js-submit-disable')) {
        e.preventDefault();
        return false;
    }
    // Prevent submitting again
    $form.data('js-submit-disable', true);
    // Set a timer to disable inputs for visual feedback
    var $inputs = $form.find(':not(:disabled)');
    setTimeout(function () { $inputs.prop('disabled', true); }, 100);
    // Unlock if the user comes back to the page
    $(window).on('focus pageshow', function () {
        $form.data('js-submit-disable', false);
        $inputs.prop('disabled', false);
    });
});
Changaco
  • 790
  • 5
  • 12
0

The problem with the method described here is that if you're using a javascript validation framework and the validation fails, you won't be able to correct and re-submit the form without refreshing the page.

To solve this, you need to plug into the success event of your validation framework and only then, set the submit control to disabled. With Parsley, you can plug into the form validated event with the following code:

$.listen('parsley:form:validated', function(e){
    if (e.validationResult) {
        /* Validation has passed, prevent double form submissions */
        $('button[type=submit]').attr('disabled', 'disabled');
  }
});
Community
  • 1
  • 1
Jon
  • 377
  • 2
  • 11
0

If you are using client-side validation and want to allow additional submit attempts if the data is invalid, you can disallow submits only when the form content is unchanged:

var submittedFormContent = null;
$('#myForm').submit(function (e) {
    var newFormContent = $(this).serialize();
    if (submittedFormContent === newFormContent)
        e.preventDefault(true);
    else 
        submittedFormContent = newFormContent;
});
Edward Brey
  • 40,302
  • 20
  • 199
  • 253
0

Found at How to prevent form resubmission when page is refreshed (F5 / CTRL+R) and solves the problem:

    <script>
        if ( window.history.replaceState ) {
            window.history.replaceState( null, null, window.location.href );
        }
    </script>
Avatar
  • 14,622
  • 9
  • 119
  • 198
-1

That is what I did to solve the problem. I disabled the button for a second with adding setTimeout twice:

- the 1st time is to let the JS form fields verification work;
- the 2nd time is to enable the button in case if you have any verification on your back end, that may return an error, and hence the user will want to try to submit the form again after editing his data.

$(document).ready(function(){
        $('button[type=submit]').on("click", function(){
            setTimeout(function () {
                $('button[type=submit]').prop('disabled', true);
                }, 0);
            setTimeout(function () {
                $('button[type=submit]').prop('disabled', false);
                }, 1000);
        });
});
Artyom P
  • 1
  • 1