Ivan
Ivan

Reputation: 103919

Form submitted multiple times when using the "submit" callback and $.ajax to post it

I've been observing some strange behavior with the following code:

$.fn.submit_to_remote = function() {
  // I use .each instead of the .submit directly so I can save
  // the 'submitEnabled' variable separately for each form
  jQuery.each($(this), function() {
    $(this).submit(function() {
      form = $(this);
      if (form.data('submitEnabled') == false) { alert('disabled'); return false; }
      form.data('submitEnabled', false);
      $.ajax({type: 'POST', url: 'url', data: data, dataType: 'script',
        success: function(script) {
          alert('success')
        }
      })
      return false;
    })
  })
}
$('.submit_to_remote').submit_to_remote();

So, basically, upon calling submit_to_remote on a form(s), it will disable it's normal submit and then make an AJAX POST request.

The strange thing is that the form gets posted multiple times, as the 'disabled' alert will show. As you can see, I'm preventing this by using a "variable" saved on the form object, and checking that variable to see if the form has already been submitted.

Upon further testing, it seems that the culprit is the script returned by the AJAX call. Let me explain a bit what I'm doing so it's more clear.

The form gets posted to the server, and a script returned. The script shows the form again, but this time with error messages for some fields. Note that the form is completely replaced.

The script, upon showing the new form, executes this:

$('.submit_to_remote').submit_to_remote();

I have to do that because otherwise, when you click on the submit button again, the form is submitted normally, no AJAX.

So, say a user submits the form and it's returned back with the appropriate errors (the 'disabled' alert is not shown). Then he submits it again; this time the 'disabled' alert is shown once. Now he submits it one more time, and this time the alert is shown twice! And so on...

So it would seem that the .submit callback is being appended again and again with each request, but why?

Could it be that by using .html() the original form is kept as a ghost or something?

Thanks!

PS: In case it's relevant, here's the script returned by the $.ajax call:

replace_content_with = 'the form and other stuff here';
$('.page-content').html(replace_content_with);
$('.submit_to_remote').submit_to_remote();

Upvotes: 23

Views: 31670

Answers (8)

Jaison James
Jaison James

Reputation: 4552

I had the same problem and fixed like below using click.

 $('.submit_to_remote').on('click', function(){
//Some validation or other stuff
$(this).submit();
});

Upvotes: 0

shell
shell

Reputation: 1937

Easier yet is:

$(".some-class").off().submit(function() {
    //Do stuff here
});

Upvotes: 5

HamidReza
HamidReza

Reputation: 1934

you can use this code to resolve :

$(this).submit(function() {
.
.
.
});

$(this).unbind("submit");

Upvotes: 0

George-Paul B.
George-Paul B.

Reputation: 584

OpenCart double submit happens because there is a submit bind in common.js.

Avoid this by using an id pattern for the form that does not match "form-".

Example: <form id="myform" >.

Upvotes: 0

fahad
fahad

Reputation: 411

Keep in mind that the jQuery submit() event looks for: <input type="submit">, <input type="image">, or <button type="submit"> in the form (http://api.jquery.com/submit/). Some frameworks default the type attribute to "submit", so if you are trying to override the default, change the type attribute to something else so it doesn't submit multiple times.

Upvotes: 1

Iliya Kolev
Iliya Kolev

Reputation: 406

Unbind didn't work for me. This did:

$(document).off('submit');
$(document).on('submit',"#element_id",function(e){
    e.preventDefault();
    //do something
}); 

I hope it helps...

In fact unbind() can bring you some troubles if you have some validation and return before submit. Example:

$(document).on('submit',"#element_id",function(e){
    e.preventDefault();
    $(document).unbind('submit');
    var name = $(this).children('input[name="name"]').val();
    if( name == 'wrong name')
        return;

    //do something
});

In this case if you input is 'wrong name' the form will not be submitted and after that, when you put the "right name", the $(document).on('submit'.. will not be triggered, neither the e.preventDefault(); and your form will be submitted in the regular way .

Upvotes: 13

KyleFarris
KyleFarris

Reputation: 17548

Yes, I agree with Seb, it's a good practice, in my opinion to always unbind before binding unless you are certain that there aren't currently binds to your element that you want. You can double bind your stuff on accident by simply using the '.submit', '.click', '.mouseover', etc... functions.

Get into the habit of doing this (never fails for me):

$('.some_element').unbind('submit').bind('submit',function() {
    // do stuff here...
});

... instead of:

$('.some_element').submit(function() {
    // do stuff here...
});

Upvotes: 62

Seb
Seb

Reputation: 25147

Not sure about this strange behavior, but seems that unbinding the submit event will do the trick.

So, before running the script returned by the $.ajax call, run this:

$('.submit_to_remote').unbind("submit");

That should remove previous bindings and leave just the new one.

Upvotes: 5

Related Questions