5

I'm using jQuery, and I'd like to make it so that a form submit won't work until all ajax calls have completed.

One way I have thought of doing this would be to store a boolean value which indicates whether there is an ajax request going on. It would be set to false at the end of every one.

I'm not sure if this is the best way though, so I'd appreciate any input.

Ben G
  • 26,091
  • 34
  • 103
  • 170
  • You could make the ajax call synchronous instead of asynchronous. That'll make the script stop while it waits for a response. – Mr Meow Jun 04 '11 at 20:54
  • @CleverQuack: It also freezes the UI in some browsers and worsens the user's experience. They should be avoided if possible. – icktoofay Jun 04 '11 at 20:55
  • @CleverQuack: That makes the browser freeze too. I would submit the form like `$('form').submit()` in the success part of the last AJAX call. – pimvdb Jun 04 '11 at 20:56
  • I want the calls to be asynchronous.. They should be able to continue to use the form freely until they click submit, with multiple asynchronous queries going on – Ben G Jun 04 '11 at 20:56
  • 1
    @babonik: So you *do* want them to be asynchronous, don't you? – pimvdb Jun 04 '11 at 20:57
  • @icktoofay I agree that it's not good UX. Just thought it might help in this situation. Sure did sound like a synchronous call. – Mr Meow Jun 04 '11 at 20:57

6 Answers6

7

Rather than use boolean, you should use an integer counter (var i=0;).

i++ every time an AJAX request is made, and

i-- every time an AJAX request is completed.

The benefits of using a counter are that it will allow you to make multiple AJAX requests at a time. With boolean, it is more buggy, because making multiple requests can cause the submit button to unlock before actions are completed.

As for the user interface, you should consider using some sort of 'loading' indicator, to show that it is working. Then, once the counter is back to zero, you can hide the loading indicator and enable the submit functionality.

Kranu
  • 2,557
  • 16
  • 22
2

A good way of handling this:

  • Change your submit button to a normal button
  • Bind a function to the submit button which runs the ajax request
  • Assign the success parameter of the jQuery AJAX request object to submit the form
8bitme
  • 897
  • 2
  • 16
  • 24
  • The thing is there are multiple ajax requests, and to save time I'd like them to occur in the background while the user operates the form. I just want all of them completed before they submit to the next page – Ben G Jun 04 '11 at 20:57
  • Then use client side validation and once all form fields are filled in correctly then go to the next page or/and post the form – 8bitme Jun 04 '11 at 20:59
  • I don't want the form submitting until the user clicks submit and all the ajaxes are done. – Ben G Jun 04 '11 at 21:00
  • You can still use the client side validation and make the jQuery success parameter increment an integer variable (instead of posting the form). When the user tries to submit check if this integer value is correct and only if it is then post the form – 8bitme Jun 04 '11 at 21:02
  • There is no specific # of ajax requests required, its just whether all the ones that have been queried are complete. So this sounds the same as my boolean idea. – Ben G Jun 04 '11 at 21:05
  • Okay, then have two counters. Counter1 increments when an AJAX request is fired off. Counter2 is incremented when an AJAX request is successful. Then if Counter1=Counter2 the form can be submitted. – 8bitme Jun 04 '11 at 21:08
  • Good idea.. I'll do this.. I see Kranu posted it as his answer as well so I'm going to accept his and upvote you for your helpfulness. – Ben G Jun 04 '11 at 21:13
2

I would approach differently and check jQuery's internal $.active or $.ajax.active (depends on version) in each ajax request's callback. if $.active is 0 then there're no more active requests and then submit the form using .submit().

This questions could be useful about $.active

Community
  • 1
  • 1
Z. Zlatev
  • 4,757
  • 1
  • 33
  • 37
  • Cool.. is there a way to check whether a certain set of requests (rather than all) are active? – Ben G Jun 04 '11 at 21:10
  • Well, the desired effect could be easily implemented using another variable. You should `++` it every time you start requests and `--` on `complete`, `error` etc – Z. Zlatev Jun 04 '11 at 21:15
1

In your onsubmit event handler, add an event.preventDefault(). In your ajax call(s)'s onComplete (or onSuccess, depending on how you want to approach it), create an $.post ajax request which sends the forms data.

If you have multiple ajax requests, you could make a counter, and increment it after each request is complete and when the counter reaches the correct amount, perform that $.ajax post.

For example:

var totalRequests = 0;
var counter = 0;
var submit = false;

$('form').submit(function(e){
e.preventDefault();
submit = true;
submitForm();
})

// starting a random number of ajax requests
for (var c=0;c<=Math.floor(Math.random()*11);c++){
totalRequests++;
$.ajax({
  url: 'ajax/'+c+'.html',
  success: function() {
       submitForm();
  }
});

function submitForm(){
    if (counter>=totalRequests && submit){
      $.post(...);
    }
}
Niklas
  • 29,752
  • 5
  • 50
  • 71
  • I don't want to submit right after the ajax is done, only when the user opts to click submit. So a counter would be pointless and this is identical to my boolean idea.. – Ben G Jun 04 '11 at 20:59
  • @babonk Perhaps wasn't quite clear on my point, I've updated my answer with an example. – Niklas Jun 04 '11 at 21:04
  • A counter is still pointless, because submit is conditional on the ajax queries all being complete, not on how many are complete. – Ben G Jun 04 '11 at 21:05
  • @babonk It **does** require every ajax query to be complete. If there are 3 queries, then set the counter to require 3 out of 3 queries to be completed. The code above sends the form when all 3 ajax queries are complete and the user submits the form, or when the user has submitted the form, and the 3rd ajax query is complete. – Niklas Jun 04 '11 at 21:07
  • There is no fixed # of queries though... It all depends on the user's interaction with the form. Certain things perform ajax requests, and those ajax requests must be complete prior to submit – Ben G Jun 04 '11 at 21:09
  • @babonk Updated my code. For each new ajax request you initiate because of the user's interaction, you would just increment totalRequests by one. The example above shows it working with any random number of ajax requests started. – Niklas Jun 04 '11 at 21:14
0

i would probably write my php file differently so i could do everything i needed in one ajax call, including the form submission. if you wanted the form to actualy submit and load a new page i would still change the php to do everything in one ajax call and then submit the in the ajax callback.

if u show some code it will be easier to understand

0

You could set the disabled attribute of the submit button to disabled when the page is first loaded, and then, after all of the AJAX queries have been through, re-enable it. It's probably a good idea to give notice to your users that data is still being sent to the form, so that they aren't confused by a disabled submit button.

To make sure that all of your queries are through, you could use the jQuery .done() method.

If you need to do client-side validation, just attach an event to your submit button:

$('#submitbutton').submit(function() {
    // function code here
});
Kevin Ji
  • 10,479
  • 4
  • 40
  • 63
  • The AJAX queries completing are a necessary but not sufficient condition for submitting. – Ben G Jun 04 '11 at 21:02
  • @babonk What else is required for the form to submit? – Kevin Ji Jun 04 '11 at 21:05
  • That they fill out the form fields. I already handle that though.. Basically my point is that AJAX being done is one of many factors, so my idea in my question was to use a boolean to indicate them being done. – Ben G Jun 04 '11 at 21:07
  • @babonk Can't you validate all of your forms within the .submit, to see that all of your preconditions have been set? – Kevin Ji Jun 04 '11 at 21:16