$ (this) dentro do sucesso AJAX não está funcionando

103

Estou tentando mudar algum código antigo que usa onclick para que eu possa usar o $ (this). O problema é que $ (this) não está funcionando quando dentro do sucesso. Existe alguma maneira de fazer isso sem defini-lo como um 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");

            }   
        }
    });

});
João magnólia
fonte

Respostas:

231

Problema

Dentro do retorno de chamada, thisrefere-se ao jqXHRobjeto da chamada Ajax, não ao elemento ao qual o manipulador de eventos estava vinculado. Saiba mais sobre como thisfunciona em JavaScript .


Soluções

Se ES2015 + estiver disponível para você, usar uma função de seta provavelmente seria a opção mais simples:

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

Você pode definir a contextopção :

Este objeto se tornará o contexto de todos os callbacks relacionados ao Ajax. Por padrão, o contexto é um objeto que representa as configurações ajax usadas na chamada ( $.ajaxSettingsmescladas com as configurações passadas para $.ajax). (...)

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

ou use $.proxy:

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

ou mantenha uma referência ao valor de thisfora do retorno de chamada:

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

Relacionados

Felix Kling
fonte
1
À medida que estou me tornando melhor com JavaScript e construindo projetos cada vez maiores e complexos, eu finalmente descobri um pouco isso, mas ver esta resposta me ajuda muito a saber que minhas suposições estão corretas e não apenas a teoria, então, pessoalmente, agradeço até se contra a política de comentários do SO! =)
JasonDavis
Concordo (e agradeço), todas as três opções funcionam. Eu não sabia sobre a opção de contexto ajax. Uma pequena desvantagem é que meu IDE (Phpstorm) não reconhece a opção que resolve o problema de escopo que detecta em fechamentos JS como este. Adicionar o proxy wrapper faz com que o aviso desapareça, portanto, contexto: deve ser um truque desconhecido em sua lista heurística presumivelmente gigantesca.
scipilot
Idem para a opção de contexto. Funcionou perfeitamente.
Anna_MediaGirl
Excelente exemplo!
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
fonte