115

I am trying to change some old code which uses onclick so that I an use the $(this). The problem is that $(this) is not working when inside the success. Is there anyway to do this without setting it as a 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
  • 16,769
  • 36
  • 159
  • 270

2 Answers2

257

Problem

Inside the callback, this refers to the jqXHR object of the Ajax call, not the element the event handler was bound to. Learn more about how this works in JavaScript.


Solutions

If ES2015+ is available to you, then using an arrow function would probably be the simplest option:

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

You can set the context option:

This object will be made the context of all Ajax-related callbacks. By default, the context is an object that represents the ajax settings used in the call ($.ajaxSettings merged with the settings passed to $.ajax). (...)

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

or use $.proxy:

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

or keep a reference to the value of this outside the callback:

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

Related

Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
  • 1
    As i'm becoming better with JavaScript and building larger and larger complex project, I had finally somewhat figured this out, but seeing this answer helps me a lot to know that my assumptions are correct and not just theory so I personally thank you, even if against SO comment policy! =) – JasonDavis Apr 29 '15 at 03:40
  • 1
    I concur (and thank), all three of these options work. I didn't know about the ajax context option. A minor drawback is that my IDE (Phpstorm) doesn't recognise the option resolves the scope issue it helpfully detects in JS closures such as this. Adding the proxy wrapper does make the warning go away, so context:this must be an unknown trick in its presumably mammoth heuristic list. – scipilot May 24 '16 at 11:52
  • Ditto for the context option. Worked perfectly. – Anna_MediaGirl Feb 06 '18 at 19:29
  • Excellent Example ! – Jawad Abdani Jun 07 '18 at 20:43
-6
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
  • 59
  • 1
  • 1
  • 10