jQuery HOW TO?? pass additional parameters to success callback for $.ajax call?
Asked Answered
S

5

19

I am trying, in vain it seems, to be able to pass additional parameters back to the success callback method that I have created for a successful ajax call. A little background. I have a page with a number of dynamically created textbox / selectbox pairs. Each pair having a dynamically assigned unique name such as name="unique-pair-1_txt-url" and name="unique-pair-1_selectBox" then the second pair has the same but the prefix is different.

In an effort to reuse code, I have crafted the callback to take the data and a reference to the selectbox. However when the callback is fired the reference to the selectbox comes back as 'undefined'. I read here that it should be doable. I have even tried taking advantage of the 'context' option but still nothing. Here is the script block that I am trying to use:

<script type="text/javascript" language="javascript">
$j = jQuery.noConflict();
function getImages(urlValue, selectBox) {
    $j.ajax({
        type: "GET",
        url: $j(urlValue).val(),
        dataType: "jsonp",
        context: selectBox,
        success:function(data){
         loadImagesInSelect(data)
        } ,
        error:function (xhr, ajaxOptions, thrownError) {
            alert(xhr.status);
            alert(thrownError);
        }

    });
}

function loadImagesInSelect(data) {
var select = $j(this);
select.empty();
$j(data).each(function() {
    var theValue = $j(this)[0]["@value"];
    var theId = $j(this)[0]["@name"];
    select.append("<option value='" + theId + "'>" + theValue + "</option>");
});
select.children(":first").attr("selected", true);

}    
</script>

From what I have read, I feel I am close but I just cant put my finger on the missing link. Please help in your typical ninja stealthy ways. TIA

****UPDATE**** Nick is a true Ninja. They should invent a new badge for that! His answer below does the trick. As he mentions it's 1.4 specific but I can live with that. Here is my final code that is working for any Ninjas in training (and my future reference):

<script type="text/javascript" language="javascript">
$j = jQuery.noConflict();
function getImages(urlValue, selectBox) {
    $j.ajax({
        type: "GET",
        url: urlValue+ '?callback=?',
        dataType: "jsonp",
        context: selectBox,
        success: jQuery.proxy(function (data) {
            var select = $j(this);
            select.empty();
            $j(data).each(function() {
                var theValue = $j(this)[0]["@value"];
                var theId = $j(this)[0]["@name"];
                select.append("<option value='" + theId + "'>" + theValue + "</option>");
            });
            select.children(":first").attr("selected", true);
        }, selectBox),
        error:function (xhr, ajaxOptions, thrownError) {
            alert(xhr.status);
            alert(thrownError);
        }
    });
}
</script>
Struve answered 8/4, 2010 at 19:54 Comment(5)
looks correct, are you getting any errors in the console? can you also paste the code where the call to getImages(urlValue, selectBox) is being made?Curagh
no errors in the console. Just on the callback selectBox is undefined. The call to the method looks like this: getImages($j('[name=txt_registry_url]').val(),$j('[name=.selImageList]'))Struve
maybe its too obvious, but does this selector work $j('[name=.selImageList]')) ? Based on the code, if nothing changes during the ajax call, selectBox should work as expected. Try logging selectBox at various points and check if the issue is it being undefined in the success callback, the loadImagesInSelect function, or maybe even getImages.Curagh
sorry fat fingered. it should read: getImages($j('[name=txt_registry_url]').val(),$j('[name=selImageList]')). But as I mentioned, the getImages method is passed the proper reference and I can inspect the default values in the debugger to verify. The reference is there all the way until the callback then it becomes undefined.Struve
Check out this answer: https://mcmap.net/q/109129/-jquery-pass-more-parameters-into-callbackZoogloea
T
13

Updated: If you're using jQuery 1.4 use this to simplify things a bit:

success: jQuery.proxy(function (data) {
    var select = $j(this);
    select.empty();
    $j(data).each(function() {
        var theValue = $j(this)[0]["@value"];
        var theId = $j(this)[0]["@name"];
        select.append("<option value='" + theId + "'>" + theValue + "</option>");
    });
    select.children(":first").attr("selected", true);
}, selectBox)
Tyler answered 8/4, 2010 at 22:25 Comment(9)
Nick, This does not seem to work. I first tried with the anonymous method and still nothing. I can see the method getting invoked but cannot step into the anonymous method. So I changed it to use the external method so I could break on it. It then comes back undefined.Struve
@Struve - How are you calling the external method? It should just be success: externalMethodName with a signature like this: function externalMethodName(data)Tyler
@Nick, I updated the original code with how I currently have it setup. It looks like this: loadImagesInSelect(data, $j(this)). Wether I pass it the reference or not, $j(this) returns back a Window object.Struve
@Struve - That's the part I'm trying to convey, you don't control which arguments are passed to that function, the format is always function(data, textStatus, XMLHttpRequest), but you can determine what this refers to inside that function by setting context: something, that something will be this when the function runs.Tyler
When I do what you suggest, change the callbacck method format to: loadImagesInSelect(data) and change the loadImagesInSelect method to: function loadImagesInSelect(data) { var select = $j(this); select.empty(); $j(data).each(function() { var theValue = $j(this)[0]["@value"]; var theId = $j(this)[0]["@name"]; select.append("<option value='" + theId + "'>" + theValue + "</option>"); }); select.children(":first").attr("selected", true); } $(this)'s type is NOT the dropdown. In IE it shows as DispHTMLWindow2. In FF its a WindowStruve
@Struve - In hopes you're using jQuery 1.4, updated the answer with a more reliable method to go about it, see if it gives you any trouble.Tyler
@Nick, you da man! This example is working perfectly. I think the previous would have worked too. The key change in addition to your suggestion was changing the param that I passed to the JSONP service. I originally had: "http://<url>:<port>?callback=loadImagesInSelect" I changed that to "http://<url>:<port>?callback=?". Thanks a million for your persistence and patience! I will update my question with the full proper code.Struve
@Struve - Welcome :) Glad this version's working, easier to understand as well I think, once you use proxy just a handful of times.Tyler
Great stuff Nick! I just used jQuery.proxy with the .each() on a jQuery UI plugin I'm currently working on. Works wonders, and is my new favorite function. jQuery.bind was my old fav. But now all jQuery events carry the ability to add pass in addition data.Jadda
D
24

This is what I did, and it also worked fine:

$.ajax('URL', {
    myCustomControl: selectBox,
    myCustomVariable: 'teste',
    data:
    {
       myData: 1
    },
    success: function (data, textStats, jqXHR) {
        myFunction(data, textStats, jqXHR, this.myCustomControl, this.myCustomVariable);
    }   
});

You can add controls and variables to the parameters of your ajax call.

Dorothydorp answered 6/9, 2013 at 12:12 Comment(1)
tested in chrome, with jquery-1.11.2 seems like, you dont really need the object: function ajaxParameterTest(p1, p2) { $.ajax({ url: "/Download.aspx?status=true", success: function(data, status, jqXHR){ callbackFunction(data, status, jqXHR, p1, p2); }, dataType: "html", statusCode:{ 404: function(){ alert("you cannot retrieve data from the server right now.."); } } }); }Ratsbane
S
14

Put this into your $.ajax parameters.

invokedata: {
    data1: "yourdata",
    data2: "moredata"
}

In the success function use it like this

this.invokedata.data1;
this.invokedata.data2;

Your $.ajax call and the success function must also be a part of the same object. Put your functions in an object and define them like this

function myObject {
    var getImage = function(..) { }
    var loadImagesInSelect = function(..) { }
}
Supersonics answered 9/4, 2010 at 0:2 Comment(4)
can you tell me what you mean by: Your $.ajax call and the success function must also be a part of the same object? Also I do not see invokeData as a parameter on the jQuery site. Can you elaborate on the values? Do they need to be strings or can they be an object reference?Struve
I have updated my answer. invokedata is stored in your object, not in jquery. Data can be anything.Supersonics
I was not able to get this working but @Nick's final answer seemed to work. Thanks for the help though. Your solution has given me a couple more ideas to try out to clean things up a bit.Struve
Check this answer, which worked for me #2542708. I was trying to do the same thing.Supersonics
T
13

Updated: If you're using jQuery 1.4 use this to simplify things a bit:

success: jQuery.proxy(function (data) {
    var select = $j(this);
    select.empty();
    $j(data).each(function() {
        var theValue = $j(this)[0]["@value"];
        var theId = $j(this)[0]["@name"];
        select.append("<option value='" + theId + "'>" + theValue + "</option>");
    });
    select.children(":first").attr("selected", true);
}, selectBox)
Tyler answered 8/4, 2010 at 22:25 Comment(9)
Nick, This does not seem to work. I first tried with the anonymous method and still nothing. I can see the method getting invoked but cannot step into the anonymous method. So I changed it to use the external method so I could break on it. It then comes back undefined.Struve
@Struve - How are you calling the external method? It should just be success: externalMethodName with a signature like this: function externalMethodName(data)Tyler
@Nick, I updated the original code with how I currently have it setup. It looks like this: loadImagesInSelect(data, $j(this)). Wether I pass it the reference or not, $j(this) returns back a Window object.Struve
@Struve - That's the part I'm trying to convey, you don't control which arguments are passed to that function, the format is always function(data, textStatus, XMLHttpRequest), but you can determine what this refers to inside that function by setting context: something, that something will be this when the function runs.Tyler
When I do what you suggest, change the callbacck method format to: loadImagesInSelect(data) and change the loadImagesInSelect method to: function loadImagesInSelect(data) { var select = $j(this); select.empty(); $j(data).each(function() { var theValue = $j(this)[0]["@value"]; var theId = $j(this)[0]["@name"]; select.append("<option value='" + theId + "'>" + theValue + "</option>"); }); select.children(":first").attr("selected", true); } $(this)'s type is NOT the dropdown. In IE it shows as DispHTMLWindow2. In FF its a WindowStruve
@Struve - In hopes you're using jQuery 1.4, updated the answer with a more reliable method to go about it, see if it gives you any trouble.Tyler
@Nick, you da man! This example is working perfectly. I think the previous would have worked too. The key change in addition to your suggestion was changing the param that I passed to the JSONP service. I originally had: "http://<url>:<port>?callback=loadImagesInSelect" I changed that to "http://<url>:<port>?callback=?". Thanks a million for your persistence and patience! I will update my question with the full proper code.Struve
@Struve - Welcome :) Glad this version's working, easier to understand as well I think, once you use proxy just a handful of times.Tyler
Great stuff Nick! I just used jQuery.proxy with the .each() on a jQuery UI plugin I'm currently working on. Works wonders, and is my new favorite function. jQuery.bind was my old fav. But now all jQuery events carry the ability to add pass in addition data.Jadda
O
4

this is Out of Scope

Just so you (or anyone else) understand(s)1, the reason that this was undefined in loadImagesInSelect() in your original example was because that function was under a different scope, and scopes don't "cascade" like that2.

When you specified a "context" of selectBox in your AJAX call, it set the context (this) for the functions given to "success" and "error". (It just so happens that they were both anonymous functions.) At this point, this is defined in both of these functions, as the value of selectBox. Now, in the function passed to "success", you call loadImagesInSelect(). When you call a function, it creates a new scope. In this scope, this will be window in non-strict mode and undefined in strict mode.


Put Graphically (in Strict Mode3):

// this = window (global scope)

$j = jQuery.noConflict();
function getImages(urlValue, selectBox) {

    // this = undefined (function scope level 1)

    $j.ajax({
        type: "GET",
        url: $j(urlValue).val(),
        dataType: "jsonp",
        context: selectBox,
        success: function(data) {

            // this = selectBox (function scope level 2)

            loadImagesInSelect(data);
        },
        error: function(xhr, ajaxOptions, thrownError) {

            // this = selectBox (function scope level 2)

            alert(xhr.status);
            alert(thrownError);
        }
    });
}

function loadImagesInSelect(data) {

    // this = undefined (function scope level 3)

    var select = $j(this);
    select.empty();
    $j(data).each(function() {
        var theValue = $j(this)[0]["@value"];
        var theId = $j(this)[0]["@name"];
        select.append("<option value='" + theId + "'>" + theValue + "</option>");
    });
    select.children(":first").attr("selected", true);
}

$.proxy() is Redundant

The use of $.proxy() in your updated code is redundant. You use $.proxy() to get this to the function that was formerly called loadImagesInSelect(), but you moved that function up into "success" anyway (instead of calling it from within "success"). It already has access now to the value of this specified by "context".

You could remove the $.proxy() wrapper around your "success" function in your updated code and it would still work.

I know it's been years since you asked your question, but I hope this helps.


  1. I hope this doesn't come across as condescending; it's not meant to be.
  2. At least, not when you call a function, and not with context. If you define a function within a function (i.e. a closure), then any variables in the outer function will be available in the inner function. However, the outer function's context (the this variable) still isn't available in the inner function.
  3. Replace undefined with window for non-strict mode.
  4. Or the native Function.prototype.bind() in ECMAScript 5.
Oceanography answered 23/2, 2015 at 21:6 Comment(0)
S
1

You can use indexValue attribute for passing :

var someData = "hello";

jQuery.ajax({
    url: "http://maps.google.com/maps/api/js?v=3",
    indexValue: {param1:someData, param2:"Other data 2", param3: "Other data 3"},
    dataType: "script"
}).done(function() {
    console.log(this.indexValue.param1);
    console.log(this.indexValue.param2);
    console.log(this.indexValue.param3);
}); 
Shaunshauna answered 24/5, 2016 at 6:46 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.