1

I am wondering why I can't change the 'this' element on AJAX success. As you can see I am attempting to swap classes and additionally add a new data attribute to the anchor tag on ajax success and it just isn't working. If I move the code outside of the success function it works perfectly... I can see it updating live when inspecting the element (only when the code is outside of success)

<a href="#" data-product-Id="@product.Id" class="lnkProduct">Add new product</a>

$(".lnkProduct").click(function (e) {
    e.preventDefault();

    var productId = $(this).attr('data-product-Id');

    $.ajax({
        type: "POST",
        url: "/Products/AddProduct",
        data: { productId: productId },
        dataType: "html",
        success: function (data) {
            $(this).addClass('lnkNewProduct').removeClass('lnkProduct');
            $(this).attr('data-newProduct-Id', data);
        }
    });
});
Pramod Karandikar
  • 5,289
  • 7
  • 43
  • 68
Blake Rivell
  • 13,105
  • 31
  • 115
  • 231

3 Answers3

1

$(this) will give a different context inside the ajax success function.Try this :-

<a href="#" data-product-Id="@product.Id" class="lnkProduct">Add new product/a>

$(".lnkProduct").click(function (e) {
        e.preventDefault();
        var $this = $(this); //store $(this) reference in a variable
        var productId = $(this).attr('data-product-Id');

        $.ajax({
            type: "POST",
            url: "/Products/AddProduct",
            data: { productId: productId },
            dataType: "html",
            success: function (data) {
                $this.addClass('lnkNewProduct').removeClass('lnkProduct'); //change here
                $this.attr('data-newProduct-Id', data); //change here
            }
        });
});
Kartikeya Khosla
  • 18,743
  • 8
  • 43
  • 69
  • 1
    `context:this,` could be used as well in ajax config.. – Rayon Feb 23 '16 at 04:24
  • This worked perfectly! I didn't realize it had a different context inside of the ajax success function. One final question: When swapping a class the way I am doing it is very strange that it doesn't fully do the styling unless I click the white space on the page. Do you know what could be causing this? Do I have to add a style to :focus also or something in my site.css? – Blake Rivell Feb 23 '16 at 04:25
  • @BlakeRivell...well I am glad that this answer worked for you...as far as your problem(mentioned above) is concerned without seeing your styling and related html it's hard to answer but I think use `.removeClass()` first before `.addClass()` or make some change in css as you mentioned above. – Kartikeya Khosla Feb 23 '16 at 04:29
  • @KartikeyaKhosla I ended up adding :focus in my css and it worked. I guess it gains focus once clicked and this was causing the style to be off until clicked on page to unfocus. Sorry about even bringing that up. Is there any reason that right after updating the class="lnkNewProduct" that when I click it again it does not go into $(".lnkNewProduct").click, and instead goes back into $(".lnkProduct").click? This is going to be a huge problem. – Blake Rivell Feb 23 '16 at 04:31
  • 1
    @BlakeRivell...I think [this link](http://stackoverflow.com/questions/8598836/jquery-dom-changes-not-appearing-in-view-source) will help you. – Kartikeya Khosla Feb 23 '16 at 04:36
  • I figured it out, I had to set both of my click functions to be $(document).on('click', '.lnkProduct'...) One other thing to note is that $this.data('newProduct-Id', data); is not working, but the attr version is. Are you sure this is correct? – Blake Rivell Feb 23 '16 at 04:45
  • @BlakeRivell....I think there must be some jquery version issue that is why `.data()` is not working for you...[see docs](https://api.jquery.com/data/) – Kartikeya Khosla Feb 23 '16 at 04:48
  • @KartikeyaKhosla I am using the latest version of jquery 2.x.. Is it only for 1.x? I don't see anything in the documentation specifying it. Yeah it is weird. This post says otherwise: http://stackoverflow.com/questions/25876274/jquery-data-not-working – Blake Rivell Feb 23 '16 at 04:51
  • @BlakeRivell...thanks for the link...updated my answer...;) – Kartikeya Khosla Feb 23 '16 at 04:53
1

$(this) gives different context inside the success function. So inside the success function instaed of this use class selector to manipulate dom element.

like this

$(".lnkProduct").click(function (e) {
e.preventDefault();

var productId = $(this).attr('data-product-Id');
var myanchor = $(this);
$.ajax({
    type: "POST",
    url: "/Products/AddProduct",
    data: { productId: productId },
    dataType: "html",
    success: function (data) {
       myanchor.addClass('lnkNewProduct').removeClass('lnkProduct');
       myanchor.attr('data-newProduct-Id', data);
    }
});
});
shu
  • 1,938
  • 10
  • 19
  • If I do this won't it update all anchor tags with .lnkProduct? I only want to update the one that was clicked. I think I should store this into a variable at the top of the click function shouldn't I? – Blake Rivell Feb 23 '16 at 04:22
  • @BlakeRivell Please check the updated answer – shu Feb 23 '16 at 04:24
1

This is the standard JS behaviour. The value of this changes depending on how a method is called.

Try using this.

$(".lnkProduct").click(function (e) {
    e.preventDefault();

    var productId = $(this).attr('data-product-Id');
    var self = $(this);
    $.ajax({
        type: "POST",
        url: "/Products/AddProduct",
        data: { productId: productId },
        dataType: "html",
        success: function (data) {
          self.addClass('lnkNewProduct').removeClass('lnkProduct');
          self.attr('data-newProduct-Id', data);
        }
    });
});
TeaCoder
  • 1,958
  • 13
  • 13