jQuery: Submit a form only if no AJAX is currently running on the page
ajax, javascript, jquery
Solution
Use jQuery's Ajax Events. As long as all of your Ajax calls are generated using jQuery, you have a way of knowing if any Ajax calls are outstanding.
$(document).ready(function() {
var ajaxBusy = false;
$(document).ajaxStart( function() {
ajaxBusy = true;
}).ajaxStop( function() {
ajaxBusy = false;
});
});
Edit:
So that answers your direct question about "How do I know if there is any Ajax call running."
Alternatively, you could disable the form's submit buttons when run your blur handler, and then re-enable it when you're done.
$('input#city').on('blur', function() {
var submit = $(this).closest('form').find(':submit:enabled');
submit.prop('disabled', true);
$.ajax('get/something?param=val').done(function(response) {
$('input:hidden[name="something"]').val(response);
}).always(function() {
submit.prop('disabled', false);
});
});
Edit 2:
So now we're at the point where we would like to delay the form submission until all current Ajax calls have completed. We let people click on the submit button, but if there are pending Ajax calls we don't do anything right away.
We can use a Deferred object to help us with this.
$(document).ready(function() {
var ajaxDefer = $.Deferred().resolve();
$(document).ajaxStart( function() {
ajaxDefer = $.Deferred();
}).ajaxStop( function() {
ajaxDefer.resolve();
});
$('form#find-users').on('submit', function() {
ajaxDefer.always(function() {
// Code here will always be executed as soon as there are no
// Ajax calls running.
// this points to the deferred object (ajaxDefer), so use the closure
// to carry over any variables you need.
});
});
});
When we're just starting out, we set up our `ajaxDefer` object in a resolved state. That means any functions attached using `.always()` will execute immediately.
When the first Ajax call starts, we replace the old `ajaxDefer` object with a new one that has not been resolved. Any new functions attached using `ajaxDefer.always()` will be deferred until later.
When the last Ajax call completes, we call `ajaxDefer.resolve()`, which causes any unexecuted deferred functions to execute. Now we're back to our initial state, where any newly-attached functions will execute immediately.
When somebody tries to submit the form, create an anonymous function that does the work and attach it to `ajaxDefer`. It will get executed when appropriate, depending on if there are any outstanding Ajax requests or not. Be mindful of your closures.
Problem
When the city input field is blurred I get somnething via an ajax request and set that as the value of a hidden field in the same form that the city field resides in. ``` $('input#city').on('blur', function() { $.ajax({ url: 'get/something?param=val', success: function(response) { $('input:hidden[name="something"]').val(response); } }); }); ``` If the user submits the form immediately after blurring off the city field sometimes due to latency the hidden field is not populated because the SQL on the other end is taking too long. The form that both these fields are in is also submitted via ajax: ``` $('form#find-users').on('submit', function() { if(NO_AJAX_CURRENTLY_RUNNING_ON_PAGE) { // do stuff } }); ``` How to detect if no ajax is running on the page? This will ensure that the city ajax was completed and the hidden field populated before the form is processed. EDIT Actually it won't, it will only prevent the form from being submitted. But if I can detect that then I can use a setInterval and keep trying to run that code until it runs because ajax is complete. Ideally there will be something in jQuery that waits until other ajax is complete and then submits.