$ (esto) dentro del éxito de AJAX no funciona

103

Estoy tratando de cambiar un código antiguo que usa onclick para poder usar $ (this). El problema es que $ (esto) no funciona cuando está dentro del éxito. ¿Hay alguna forma de hacer esto sin configurarlo como 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
fuente

Respuestas:

231

Problema

Dentro de la devolución de llamada, se thisrefiere al jqXHRobjeto de la llamada Ajax, no al elemento al que estaba vinculado el controlador de eventos. Obtenga más información sobre cómo thisfunciona en JavaScript .


Soluciones

Si ES2015 + está disponible para usted, entonces usar una función de flecha probablemente sería la opción más simple:

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

Puede configurar la contextopción :

Este objeto se convertirá en el contexto de todas las devoluciones de llamada relacionadas con Ajax. De forma predeterminada, el contexto es un objeto que representa la configuración de ajax utilizada en la llamada ( $.ajaxSettingscombinada con la configuración pasada $.ajax). (...)

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

o use $.proxy:

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

o mantener una referencia al valor de thisfuera de la devolución de llamada:

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

Relacionado

Felix Kling
fuente
1
A medida que estoy mejorando con JavaScript y construyendo un proyecto complejo cada vez más grande, finalmente me di cuenta de esto, pero ver esta respuesta me ayuda mucho a saber que mis suposiciones son correctas y no solo teóricas, así que personalmente les agradezco, incluso si está en contra de la política de comentarios SO! =)
JasonDavis
Estoy de acuerdo (y agradezco) que las tres opciones funcionan. No sabía sobre la opción de contexto ajax. Un inconveniente menor es que mi IDE (Phpstorm) no reconoce que la opción resuelve el problema de alcance que detecta útilmente en cierres de JS como este. Agregar el contenedor de proxy hace que la advertencia desaparezca, así que contexto: este debe ser un truco desconocido en su presuntamente gigantesca lista heurística.
scipilot
Lo mismo ocurre con la opción de contexto. Funcionó perfectamente.
Anna_MediaGirl
¡Excelente ejemplo!
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
fuente