user967451
user967451

Reputation:

jQuery: Submit a form only if no AJAX is currently running on the page

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.

Upvotes: 5

Views: 5256

Answers (5)

wild_nothing
wild_nothing

Reputation: 3023

Use this to check if AJAX calls are currently in-progress using JQuery:

if ($.active == 0) {
  ...
}

Upvotes: 3

slashingweapon
slashingweapon

Reputation: 11307

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.
        });
    });
});
  1. 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.

  2. 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.

  3. 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.

  4. 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.

Upvotes: 14

sayannayas
sayannayas

Reputation: 774

What i could have done on this circumstances is to use plugin like block ui or disable the form submit button,the reason is you need to be interactive in your design,you may well able to lock the form submission,but its better to give a message or have a modal gray out

Upvotes: 0

Jaime Torres
Jaime Torres

Reputation: 10515

Use a lock variable like you suggested:

$('input#city').on('blur', function() {
    window.AJAX_CURRENTLY_RUNNING_ON_PAGE = true;
    $.ajax({
        url: 'get/something?param=val',
        success: function(response) {
            $('input:hidden[name="something"]').val(response);
        },
        complete: function() { window.AJAX_CURRENTLY_RUNNING_ON_PAGE = false; }
    });
});

$('form#find-users').on('submit', function() {
    if(window.AJAX_CURRENTLY_RUNNING_ON_PAGE) {
        return;
    }
    //dostuff
});

Upvotes: 1

NappingRabbit
NappingRabbit

Reputation: 1918

you can put a variable in the global namespace, perhaps named ajaxLock and toggle it on when AJAX starts and off when the response comes. Then check it before allowing submit.

something like

var ajaxLock = 1;
$('input#city').on('blur', function() {
$.ajax({
    url: 'get/something?param=val',
    success: function(response) {
        $('input:hidden[name="something"]').val(response);
        ajaxLock = 0;
    }
    });
});

Upvotes: 1

Related Questions