TARKUS
TARKUS

Reputation: 2200

How to construct and invoke method or function in generic jquery ajax call

I'm trying to construct a generic Ajax function by passing the few properties required by a jQuery Ajax object as object parameters. I'm stuck on one piece of the puzzle, that is the proper way to pass the callback function within "done". The idea is to replace about 10 ajax functions in my .js file with just one ajax function.

Here's my code:

// The generic ajax function, which will be called by various functions
// and passing variable parameters, different controller urls, different
// GET or POST types, different POST data sets, and finally, different
// callback functions.
function generalAjax(params){
    $.ajax({
        url: params.url,
        type: params.type,
        data : params.formData,
        dataType : 'json'
    }).done(function( data ) {
        params.callback; // <-- Trying to get this line to work.
    }).fail(function(jqXHR, textStatus){
        var string = "Ajax request failed : " + textStatus + " - " + jqXHR.responseText;
        $("#diag").html(string);
    });
}   

// Create the prototype
function ajaxParams(url, type, data, callback) {
    this.url = url;
    this.type = type;
    this.formData = data;
    this.callback = callback;
}

// A button in my php file will call this function.
function nameSearch(){
    var url = "/ajax/name_search/";
    var type = "POST";
    var formData = { 'q' : document.getElementsByName("searchname")[0].value };
    var callback = nameSearchCallback; // Specific method for this event
    var params = new ajaxParams(url, type, formData, callback);
    generalAjax(params);
}

// One specific callback function for one specific event trigger.
function nameSearchCallback(e){
    var string = "";
    $.each(e,function(k,v){
        string += k + " = " + v + "\n";
        if(v instanceof Object == true){
            string += "<ul>\n";
            $.each(v,function(kk,vv){
                string += "<li>" + kk + " = " + vv + "</li>\n";
            });
            string += "</ul>\n";
        }
    });
    $("#form-panel").html(string);
}

15 lines down, you can see where I've substituted parameters.callback for a hard coded script or direct call to a specific function. What I want is for that line to call different functions or methods, depending on the needs of the instantiated object calling the genericAjax function.

Depending upon whether I try params.callback or params.callback(), at best, nothing happens, or at worst, the page refreshes and in my javascript console I get a TypeError : a is undefined in the jquery library file.

I have also tried var callback = nameSearchCallback; and var callback = nameSearchCallback(); I have also skipping the reference to the nameSearchCallback() function, and just writing the function into params.callback as

params.callback = function(){
    var string = "";
    $.each(e,function(k,v){
        string += k + " = " + v + "\n";
        if(v instanceof Object == true){
            string += "<ul>\n";
            $.each(v,function(kk,vv){
                string += "<li>" + kk + " = " + vv + "</li>\n";
            });
            string += "</ul>\n";
        }
    });
    $("#diag").html(string);
}

Upvotes: 0

Views: 1318

Answers (1)

TARKUS
TARKUS

Reputation: 2200

I have a working solution to my problem, but it isn't a specific answer to my question. Since nobody is answering the question, I guess I'll post the general solution.

I came across a question with an answer on how to make dynamic functions using arrays. I applied this answer to the above question.

I declare an array:

var dyn_functions = [];

Every time I want to define a callback function, I write something like this:

// Where data is an object and data['string'] is a property returned in jsson format from a php controller.
dyn_functions['nameSearchCallback'] = function (data){
    var string = "<h3>Search results:</h3>\n";
    string += "<blockquote>" + data['string'] + "</blockquote>";
    $("#form-panel").html(string);
}

Every callback function will have its own name.

Your event trigger will call its own function, something like

var n = "Mark";
<button onClick='nameSearch(n);return false;'>Search</button>

In your script file, the event function nameSearch looks like this:

function nameSearch(n){
    var url = "/ajax/name_search/"; //This is the name of a php file or a function in an MVC controller
    var type = "POST"; //This can also be GET
    var formData = { 'q' : n }; //If your type is "GET", then this should be empty, like "", and you could pass `n` as a url query string or a uri segment.
    var callback = "nameSearchCallback"; //Remember the dynFunction callback above? This is the name of it.
    var params = new ajaxParams(url, type, formData, callback);//Make a params object to pass our params to the generic ajax function.
    generalAjax(params); //Calling the generic ajax function.
}

You need to prototype the params property constructor:

// The prototype constructor for the general Ajax parameters.
function ajaxParams(url, type, data, callback) {
    this.url = url;
    this.type = type;
    this.formData = data;
    this.callback = callback;
}

...and finally, we have one single ajax function that serves infinite n of calls:

// The general Ajax function.
function generalAjax(params){
    $.ajax({
        url: params.url,
        type: params.type,
        data : params.formData,
        dataType : 'json'
    }).done(function( data ) {
        var callback = dyn_functions[params.callback](data);
    }).fail(function(jqXHR, textStatus){
        var string = "Ajax request failed : " + textStatus + " - " + jqXHR.responseText;
        $("#diag").html(string);
    });
}

So, the whole thing all together will look like this:

// The prototype constructor for the general Ajax parameters.
function ajaxParams(url, type, data, callback) {
    this.url = url;
    this.type = type;
    this.formData = data;
    this.callback = callback;
}

// The general Ajax function.
function generalAjax(params){
    $.ajax({
        url: params.url,
        type: params.type,
        data : params.formData,
        dataType : 'json'
    }).done(function( data ) {
        var callback = dyn_functions[params.callback](data);
    }).fail(function(jqXHR, textStatus){
        var string = "Ajax request failed : " + textStatus + " - " + jqXHR.responseText;
        $("#diag").html(string);
    });
}



//The global dyn_functions object, to be used for all scripts.
var dyn_functions = [];

dyn_functions['nameSearchCallback'] = function (data){
    var string = "<h3>Search results:</h3>\n";
    string += "<blockquote>" + data['string'] + "</blockquote>";
    $("#form-panel").html(string);
}

function nameSearch(n){
    var url = "/ajax/name_search/";
    var type = "POST";
    var formData = { 'q' : n }; //If your type is "GET", then this should be empty, like "", and you could pass `n` as a url query string or a uri segment.
    var callback = "nameSearchCallback";
    var params = new ajaxParams(url, type, formData, callback);
    generalAjax(params);
}

Upvotes: 1

Related Questions