web-dev-qa-db-fra.com

jQuery COMMENT ?? transmettre des paramètres supplémentaires à callback success pour un appel $ .ajax?

J'essaie, en vain, semble-t-il, de pouvoir transmettre des paramètres supplémentaires à la méthode de rappel de réussite que j'ai créée pour un appel ajax réussi. Un peu de fond J'ai une page avec un certain nombre de paires zone de texte/zone de sélection créées dynamiquement. Chaque paire ayant un nom unique attribué dynamiquement, tel que name = "unique-paire-1_txt-url" et name = "unique-pair-1_selectBox", la seconde paire a le même mais le préfixe est différent.

Dans un effort de réutilisation du code, j'ai conçu le rappel pour récupérer les données et une référence à la zone de sélection. Toutefois, lorsque le rappel est déclenché, la référence à la zone de sélection revient sous la forme "indéfini". J'ai lu ici que cela devrait être faisable. J'ai même essayé de tirer parti de l'option "contexte" mais toujours rien. Voici le bloc de script que j'essaie d'utiliser:

<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>

D'après ce que j'ai lu, je me sens proche mais je n'arrive pas à mettre le doigt sur le chaînon manquant. S'il vous plaît aider de votre manière furtive typique de ninja. TIA

**** UPDATE **** Nick est un vrai Ninja. Ils devraient inventer un nouveau badge pour ça! Sa réponse ci-dessous fait le tour. Comme il le mentionne, il est spécifique à 1,4 mais je peux vivre avec cela. Voici mon code final qui fonctionne pour tous les Ninjas en formation (et ma future référence):

<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>
17
dotnetgeek

Mise à jour: Si vous utilisez jQuery 1.4, utilisez ceci pour simplifier un peu les choses:

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)
12
Nick Craver

C'est ce que j'ai fait et cela a également bien fonctionné:

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

Vous pouvez ajouter des contrôles et des variables aux paramètres de votre appel ajax.

22
ClayKaboom

Mettez ceci dans vos paramètres $ .ajax.

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

Dans la fonction de réussite, utilisez-le comme ceci

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

Votre appel $ .ajax et la fonction de réussite doivent également faire partie du même objet. Placez vos fonctions dans un objet et définissez-les comme ceci

function myObject {
    var getImage = function(..) { }
    var loadImagesInSelect = function(..) { }
}
12
Egor Pavlikhin

this est hors de portée

Juste pour que vous (ou qui que ce soit d'autre) comprenne (nt)1, La raison pour laquelle this n'était pas défini dans loadImagesInSelect() dans votre exemple d'origine était parce que cette fonction était sous une étendue différente et que les étendues ne "cascadaient" pas comme ça2.

Lorsque vous spécifiez un "contexte" de selectBox dans votre appel AJAX, il définit le contexte (this) des fonctions attribuées à "succès" et "erreur". (Il se trouve que ces deux fonctions étaient anonymes.) À ce stade, this est défini dans ces deux fonctions, en tant que valeur de selectBox. Maintenant, dans la fonction passée à "success", vous appelez loadImagesInSelect(). Lorsque vous appelez une fonction, une nouvelle portée est créée. Dans cette étendue, this sera window en mode non strict et undefined en mode strict.


Mettre graphiquement (en mode strict3):

// 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() est redondant

L'utilisation de $.proxy() dans votre code mis à jour est redondante. Vous utilisez $.proxy() pour obtenir this à la fonction qui s'appelait auparavant loadImagesInSelect(), mais vous avez quand même déplacé cette fonction vers "succès" (au lieu de l'appeler de "succès"). Il a déjà accès à la valeur this spécifiée par "context".

Vous pouvez supprimer le wrapper $.proxy() autour de votre fonction "success" dans votre code mis à jour et cela fonctionnerait toujours.

Je sais que cela fait des années que vous avez posé votre question, mais j'espère que cela vous aidera.


  1. J'espère que cela ne semble pas condescendant; ce n'est pas censé être.
  2. Du moins, pas lorsque vous appelez une fonction, et pas avec le contexte. Si vous définissez une fonction dans une fonction (c'est-à-dire une fermeture), toutes les variables de la fonction externe seront disponibles dans la fonction interne. Cependant , le contexte de la fonction externe (la variable this) n'est toujours pas disponible dans la fonction interne.
  3. Remplacez undefined par window pour le mode non strict.
  4. Ou la Function.prototype.bind() native dans ECMAScript 5.
3
Hutch Moore

Vous pouvez utiliser indexValue attribut pour transmettre: 

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);
}); 
0
aecavac