skiwi
skiwi

Reputation: 69259

jQuery - Do action when all ajax have completed

I've read about the jQuery's Deferred object, but I can't seem to make much sense out of it, here's my problem, I've got the following code:

function preprocess(form) {
    $(form).find(".input input").each(function() {
        var required = $(this).attr("required");
        var checkField = $(this).closest(".inputcontainer").children(".check");
        var errorField = $(this).closest(".inputcontainer").children(".errormessage");
        if (typeof required !== 'undefined') {
            $(checkField).each(function() {
                $(this).css("color", "#FFFF00");
                $(this).html("✘");
            });
            $(errorField).each(function() {
                $(this).css("color", "#FFFF00");
                $(this).html("(Required)");
            });
        }
        else {
            $(checkField).each(function() {
                $(this).css("color", "#FFFF00");
                $(this).html("✔");
            });
            $(errorField).each(function() {
                $(this).css("color", "#000000");
                $(this).html("");
            });
        }
    });

    $(form).find("datalist").each(function() {
        var datalist = $(this);
        callService({
            name: "datalist_" + $(this).attr("id"),
            data: { },
            success: function(json) {
                $(json).each(function() {
                    var html = "";
                    $(this.options).each(function() {
                        html += "<option value='" + this.value + "'>";
                    });
                    $(datalist).append(html);
                });
            }
        });
    });

    $(form).find("select").each(function() {
        var select = $(this);
        callService({
            name: "select_" + $(this).attr("name"),
            data: { },
            success: function(json) {
                $(json).each(function() {
                    var html = "";
                    $(this.options).each(function() {
                        html += "<option value='" + this.id + "'>" + this.value + "</option>";
                    });
                    $(select).append(html);
                });
            }
        });
    });
}

This code prepares a form to be ready to be presented to the user, which involves AJAX calls, which I have wrapped in a callService({}); call, what you can see is the following:

Then I also have the following (simplified):

function setContent(html, url) {
    html = $.parseHTML(html);
    $(html).filter("form").each(function() {
        preprocess($(this));
    });
    $("#pagemain").html(html);
}

This gets html from an AJAX call, then calls preprocess on all its forms and updates the #pagemain.
However now data is being displayed before the preprocess has completely finished.

The question: How can I do the $("#pagemain").html(html); after preprocessed ánd involving AJAX processes, have been finished?

Upvotes: 0

Views: 216

Answers (3)

Brett
Brett

Reputation: 4269

Deferred's can be a little intimidating to learn at first, but, like most things, once the light bulb goes on and you get it, it's pretty simple. The simple setup for creating a deferred object is like this:

var defer = $.Deferred(function(dfd) {
 // do the processing you need, and then...
 // when processing is complete, make a call to...
 dfd.resolve(/* return data goes here, if required */);
}).promise();

// use the deferred object like it was an ajax call
defer.then(/* do the stuff that needed to wait */);

So, using your example:

function setContent(html, url) {
  html = $.parseHTML(html);

  var defer = $.Deferred(function(dfd) {
    $(html).filter("form").each(function() {
      preprocess($(this));
    });

    dfd.resolve();
  }).promise();

  defer.then($("#pagemain").html(html));
}

Upvotes: 1

ProllyGeek
ProllyGeek

Reputation: 15836

neat solution will be using when :

http://api.jquery.com/jQuery.when/

    $.when( {//your preprocessing function here
 } ).done(function( x ) {
      //your done action here
    });

Upvotes: 0

Khanh TO
Khanh TO

Reputation: 48972

Try:

function preprocess(form) {
    //Your above code is omitted for brevity
    var promises = [];

    $(form).find("datalist").each(function() {
        var defered = $.Deferred();//create a defered object
        promises.push(defered.promise());//store the promise to the list to be resolved later

        var datalist = $(this);
        callService({
            name: "datalist_" + $(this).attr("id"),
            data: { },
            success: function(json) {
                $(json).each(function() {
                    var html = "";
                    $(this.options).each(function() {
                        html += "<option value='" + this.value + "'>";
                    });
                    $(datalist).append(html);
                });
                defered.resolve();//resolve the defered when ajax call has finished
            }
        });
    });

    $(form).find("select").each(function() {
        var defered = $.Deferred();//create a defered object
        promises.push(defered.promise());//store the promise to the list to be resolved later
        var select = $(this);
        callService({
            name: "select_" + $(this).attr("name"),
            data: { },
            success: function(json) {
                $(json).each(function() {
                    var html = "";
                    $(this.options).each(function() {
                        html += "<option value='" + this.id + "'>" + this.value + "</option>";
                    });
                    $(select).append(html);
                });
                defered.resolve();//resolve the defered when ajax call has finished
            }
        });
    });
    return promises;
}

Your setContent:

function setContent(html, url) {
    html = $.parseHTML(html);
    var promises = [];
    $(html).filter("form").each(function() {
        promises = promises.concat(preprocess($(this)));//Concatenating all promises arrays
    });

    $.when.apply($,promises).then(function(){// Use $.when to execute a function when all deferreds are resolved.
        $("#pagemain").html(html);
    });
}

Upvotes: 2

Related Questions