Reputation: 64
I want to run code after multiple ajax calls finish. A .each()
loop calls .update()
on all checkboxes, and their change event runs the ajax code.
I have a group of checkboxes that each send off an ajax request when checked. A checkbox at the top will update all child checkboxes to match the top checkbox.
I called the .change()
function to avoid duplicate code, as their change events already sent the ajax request. The on change code hides the child checkbox and the success function makes the checkbox visible again.
I want to hide the parent checkbox, and show it only after all children are done updating with the multiple ajax requests.
<head>
<script type="text/javascript" src="//code.jquery.com/jquery-1.10.2.js"></script>
</head>
<body>
<script>
$(document).ready(function () {
// Calls change event for all child checkboxes
// I want it to hide this checkbox until all child ajax calls are complete
$('#wrapper').on('change', '.parent-active', function () {
var checkbox = $(this);
checkbox.css('display', 'none').after('<img src="loading.gif"/>');
var data = $('#category-content');
var boxes = data.find('input[type=checkbox]');
boxes.each(function( index, box ){
if($(box).is(':checked') != $(checkbox).is(':checked')){
$(box).prop('checked', $(checkbox).is(':checked')).change();
}
});
checkbox.css('display', 'inline').next().remove();
});
// Hides checkbox, displays loading image, sends ajax, restores checkbox
$('#wrapper').on('change', '.child-active', function () {
var checkbox = $(this);
checkbox.css('display', 'none').after('<img src="loading.gif"/>');
$.ajax({
url: '/',
type: 'post',
complete: function (data) {
checkbox.css('display', 'inline').next().remove();
}
});
});
});
</script>
<div id="wrapper">
<table><tbody>
<tr><td>Parent</td><td><input type="checkbox" class="parent-active" id="parent-active-1"/></td></tr>
</tbody></table>
<div id ="category-content"><table><tbody>
<tr><td>Child 1</td><td><input type="checkbox" class="child-active" id="child-active-1"/></td></tr>
<tr><td>Child 2</td><td><input type="checkbox" class="child-active" id="child-active-2"/></td></tr>
<tr><td>Child 3</td><td><input type="checkbox" class="child-active" id="child-active-3"/></td></tr>
</tbody></table></div>
</div>
The problem is that the parent checkbox doesn't even show the loading image. The .change()
calls return instantly, and the parent checkbox is restored before you can even see it deactivate. I'd like to keep the parent checkbox unavailable until the children are all finished.
I've tried using .promise()
and .when()
but haven't figured out a solution yet.
How can I react to multiple ajax requests?
If you want to see a stripped down version of the page, check http://dl.dropboxusercontent.com/u/4621872/stackoverflow.html
Upvotes: 1
Views: 2879
Reputation: 14053
With jQuery Deferred, it's pretty simple to wait for a bunch of AJAX calls to complete, e.g.:
var deferreds = [];
$sel.each(function() {
deferreds.push(
$.ajax(); // make AJAX call for element $(this)
);
});
$.when.apply($, deferreds).done(function() {
// all AJAX calls have complete
do_something();
});
For example, if you wanted to prefetch all images
var deferreds = [];
$('img').each(function() {
deferreds.push(
$.ajax($(this).attr('src'));
);
});
$.when.apply($, deferreds).done(function() {
// all images are now prefetched
});
Upvotes: 3