$ (this) à l'intérieur du succès AJAX ne fonctionne pas

103

J'essaie de changer un ancien code qui utilise onclick afin que j'utilise le $ (this). Le problème est que $ (this) ne fonctionne pas à l'intérieur du succès. Est-il possible de le faire de toute façon sans le définir comme var.

$('.addToCart').click(function() {

    $.ajax({
        url: 'cart/update',
        type: 'post',
        data: 'product_id=' + $(this).attr("data-id"),
        dataType: 'json',
        success: function(json) {

            if (json['success']) {

            $(this).addClass("test");

            }   
        }
    });

});
John Magnolia
la source

Réponses:

231

Problème

Dans le rappel, thisfait référence à l' jqXHRobjet de l'appel Ajax, pas à l'élément auquel le gestionnaire d'événements était lié. En savoir plus sur le thisfonctionnement de JavaScript .


Solutions

Si ES2015 + est disponible pour vous, utiliser une fonction fléchée serait probablement l'option la plus simple:

$.ajax({
    //...
    success: (json) => {
         // `this` refers to whatever `this` refers to outside the function
    }
});

Vous pouvez définir l' contextoption :

Cet objet deviendra le contexte de tous les rappels liés à Ajax. Par défaut, le contexte est un objet qui représente les paramètres ajax utilisés dans l'appel ( $.ajaxSettingsfusionnés avec les paramètres passés à $.ajax). (...)

$.ajax({
    //...
    context: this,
    success: function(json) {
         // `this` refers to the value of `context`
    }
});

ou utilisez $.proxy:

$.ajax({
    //...
    success: $.proxy(function(json) {
         // `this` refers to the second argument of `$.proxy`
    }, this)
});

ou gardez une référence à la valeur de l' thisextérieur du rappel:

var element = this;

$.ajax({
    //...
    success: function(json) {
         // `this` refers to the jQXHR object
         // use `element` to refer to the DOM element
         // or `$(element)` to refer to the jQuery object
    }
});

en relation

Félix Kling
la source
1
Au fur et à mesure que je m'améliore avec JavaScript et que je construis des projets complexes de plus en plus grands, j'avais finalement un peu compris cela, mais voir cette réponse m'aide beaucoup à savoir que mes hypothèses sont correctes et pas seulement de la théorie, donc je vous remercie personnellement, même si contre la politique de commentaire SO! =)
JasonDavis
Je suis d'accord (et je remercie), ces trois options fonctionnent. Je ne connaissais pas l'option contextuelle ajax. Un inconvénient mineur est que mon IDE (Phpstorm) ne reconnaît pas l'option résout le problème de portée qu'elle détecte utilement dans les fermetures JS comme celle-ci. L'ajout du wrapper de proxy fait disparaître l'avertissement, donc contexte: cela doit être une astuce inconnue dans sa liste heuristique vraisemblablement gigantesque.
scipilot
Idem pour l'option contextuelle. A parfaitement fonctionné.
Anna_MediaGirl
Excellent exemple!
Jawwad Rizwan
-2
jQuery(".custom-filter-options .sbHolder ul li a").each(function () {
    var myStr = jQuery(this).text();
    var myArr = myStr.split(" (");
     url = 'your url'; // New Code
            data = myArr[0];
                try {
                    jQuery.ajax({
                        url : url,
                        context: this,
                        type : 'post',
                        data : data,
                        success : function(data) {
            if(data){
                  jQuery(this).html(data);
            }else{
                  jQuery(this).html(myArr[0]);
            }
                        }
                    });
                } catch (e) {
                } 


});
Vishal Sanwar
la source