9

I am working on a dynamic online form website. In the main form, I have multiple sub-forms which can be added and deleted dynamically.

<div class='subform'>
    //form fields 
    <input ...>
    ...
    <button class='subform_submit'>
</div>

For each subform, I bind an AJAX call on the subform's submit button like this:

$('#main').on('click', '.subform_submit', function(){
    // Get this subform's user input
    ...
    $.ajax({
        url: ..,
        type: ..,
        data: /* this subform's data */
    });
});

So in that page, I may have 0 to 10 subforms depending on the user's selection. I also have a main submit button on the bottom of the page, which can submit those subforms and the main form's data together.

$('#main').on('click', '#submit', function(e){
    $('.subform_submit').click(); // Submit each subform
    bootbox.confirm({ });
})

Once main submit button is clicked, I want to show a loading picture and then show a dialog box (I use bootbox.confirm() here) until all AJAX calls have completed. This dialog box is telling user that whole form including sub-forms has been submitted. But the problem is that each AJAX call may take 2 seconds to complete and I don't know how may calls may be pending completion. How can I write this main submit button so that it will:

  1. Show the loading image immediately, and
  2. Hide the loading image and show the dialog box after all AJAX calls have completed?
monknom
  • 137
  • 1
  • 4

5 Answers5

4

Keep track of how many sub-forms there are;

$subFormsCount = $('.subform').length;

Keep track of how many forms have been submitted;

$submittedForms = 0;

Each time a form finishes submitting, add to the $submittedForms;

$.ajax({
  ..
  ..
  done: function(){
    $submittedForms++;
  }
})

Create a global timer to see if the number of submitted forms matches the total number of subforms. If true, hide the dialog box;

setInterval(function(){
  if($submittedForms == $subFormsCount){
   $('.dialog').show();
  }
}, 50ms)

Edit

You could skip the global timer (as this will probably be a few milliseconds out) - include the check in your ajax.done instead;

$.ajax({
  ..
  ..
  done: function(){
    $submittedForms++;

    if($submittedForms == $subFormsCount){
     $('.dialog').show();
    }
  }
})
Lewis
  • 3,479
  • 25
  • 40
  • where should put dialog box code ? If check in ajax.done, what if there is 0 subforms there and I still want to see dialog box? – monknom Dec 22 '15 at 17:13
  • @monknom I'm not sure what you're asking. I thought you wanted to show an image whilst subforms were submitting and the dialog box only when they had finished? – Lewis Dec 22 '15 at 17:25
  • Sorry about my poor english, image is for subforms submitting. but dialog box I want to tell people whole form has been submitted not only subform – monknom Dec 22 '15 at 17:27
  • Would the code above not work for this? Both $submittedForms and $subFormsCount would == 0 and therefore match, which should display the dialog? I'm not sure I fully understand your problem and perhaps someone else can help further. – Lewis Dec 22 '15 at 17:35
  • @monknom Glad to hear it! Good luck with your project. – Lewis Dec 22 '15 at 17:39
2

You want to use .done() in order to specify code that should wait until the AJAX asynchronous function completes.

 $.ajax({
     url:..,
     type: ..,
     data: /* this subform's data*/ })
     .done(function() {
         //Put code here
     });
1

Have you tried .ajaxStop() event handler ?

$(document).ajaxStop(function() {
  // place code to be executed on completion of last outstanding ajax call here
});

also, check this answer

Community
  • 1
  • 1
WinK-
  • 372
  • 2
  • 14
0

I assume you have 9 subform and 1 main form. Code for 8 subform will be same.

I use here async:false : Means next ajax will not be call until 1st one is not completed.

Sample Code Format :

var id = 5;
$.ajax({
    url:  ,
    type: 'POST',
    data: {'id':id},
    dataType: 'JSON',
    async: false,
    error : function(xhr, textStatus, errorThrown) {
        alert('An error occurred!');
    },
    success : function(response){

    }
});

Just set variable in your last sub form that is 9th subform.

success : function(response){
        var counter = true;
    }

if(counter){
    /* Code to show dialog.*/
}
Monty
  • 1,110
  • 7
  • 15
0

You can use $.when to wait for each request to complete. Something like this should get you close. You'd basically want to store all the ajax requests in an array and pass that to when as the arguments.

$('#main').on('click', '.subform_submit', function () {

  var formRequests = $('.subform').map(function () {
    var $form = $(this);
    return $.ajax({
      url: '',
      data: $form.serialzeArray()
    });
  }).get();

  $.when.apply(undefined, formRequests).done(function () {
    console.log('All done!');
  });

});

Here goes a very similar little demo I just made up: https://jsfiddle.net/g9a06y4t/

Bill Criswell
  • 32,161
  • 7
  • 75
  • 66