27

I have this ajax call to a doop.php.

    function doop(){
        var old = $(this).siblings('.old').html();
        var new = $(this).siblings('.new').val();

        $.ajax({
            url: 'doop.php',
            type: 'POST',
            data: 'before=' + old + '&after=' + new,
            success: function(resp) {
                if(resp == 1) {
                    $(this).siblings('.old').html(new);
                }
            }
        });

        return false;
    }

My problem is that the $(this).siblings('.old').html(new); line isn't doing what it's supposed to do.

thanks.. all helpful comments/answers are voted up.

Update: it appears that half of the problem was the scope (thanks for the answers that helped me clarify that), but the other half is that I'm trying to use ajax in a synchronous manner. I've created a new post

Sumurai8
  • 20,333
  • 11
  • 66
  • 100
Chris
  • 8,736
  • 18
  • 49
  • 56
  • 8
    Whoa whoa whoa whoa whoa. `new` is a reserved word: https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Reserved_Words – Crescent Fresh Oct 15 '09 at 03:31
  • 3
    Don't worry about new, it's called something else in my code. Just called it new to make the code more understandable for you guys – Chris Oct 15 '09 at 03:40

3 Answers3

52

You should use the context setting as in http://api.jquery.com/jQuery.ajax/

function doop(){
    var old = $(this).siblings('.old').html();
    var newValue = $(this).siblings('.new').val();

    $.ajax({
        url: 'doop.php',
        type: 'POST',
        context: this,
        data: 'before=' + old + '&after=' + newValue,
        success: function(resp) {
            if(resp == 1) {
                $(this).siblings('.old').html(newValue);
            }
        }
    });

    return false;
}

"this" will be transfer to the success scope and will act as expected.

Guillaume Bois
  • 1,302
  • 3
  • 15
  • 23
  • You really should not use reserved words like `new` as variable names. – Tomalak Jun 03 '12 at 18:35
  • Agreeing with Nick - this is the correct approach. Consider that the "save it in another variable" approach won't work if you have function "doop" called when one of multiple buttons are clicked or some other such duplication. – Tim Holt Sep 28 '12 at 20:38
  • +1 Much more flexible answer than the selected one, in our case, the var would have to be unique for every single item in a very long list of items adding code bloat, this is a few short characters and gives much more flexible use cases. – oucil Jun 24 '13 at 14:12
26

First of all new is a reserved word. You need to rename that variable.

To answer your question, Yes, you need to save this in a variable outside the success callback, and reference it inside your success handler code:

var that = this;
$.ajax({
    // ...
    success: function(resp) {
        if(resp == 1) {
            $(that).siblings('.old').html($new);
        }
    }
})

This is called a closure.

Crescent Fresh
  • 115,249
  • 25
  • 154
  • 140
  • Hmm, weird, I tried something very similar to what you've done, but I did `var saveit = $(this);` didn't work. I'll try this one now.. Also don't worry about new, it's called something else in my code. – Chris Oct 15 '09 at 03:42
  • @Chris: re: `new`, I figured as much. :) – Crescent Fresh Oct 15 '09 at 03:43
  • @Chris: re the closure not working, make sure `doop` is itself referring to the expected `this`. If you just call `doop()` for example, `this` will just point to the `window` object. – Crescent Fresh Oct 15 '09 at 03:53
  • Ok, after the closure, I'm able to target the right this/that (I tested it with show/hide and i know it's targeting the right thing). However, it's not updating the html.. I'm doing some troubleshooting and will update my answer above, please check back when you get a chance, thanks. – Chris Oct 15 '09 at 04:18
  • Now that I've done my troubleshooting, I've come to the conclusion that the second half of the problem is that I should be using synchronous ajax. not asynchronous. Updaing my question above and posting a new question. – Chris Oct 15 '09 at 13:34
  • You're correct on the `new` keyword, but this adds far too much code bloat in a long list where it's added dynamically, each var would have to be unique, where as in the answer below, using `context: this` does it once and has much more flexible use cases. – oucil Jun 24 '13 at 14:14
7

this is bound to the object to which the executing function was applied. That could be some AJAX response object, or the global object (window), or something else (depending on the implementation of $.ajax.

Do I need to capture $(this) into a variable before entering the $.ajax call, and then pass it as a parameter to the $.ajax call? or do I need to pass it to the anonymous success function? If that's going to solve the problem, where do I pass it to the $.ajax?

You do indeed need a way to capture the value of this before defining the success function. Creating a closure is the way to do this. You need to define a separate variable (e.g. self):

function doop() {
    var old = $(this).siblings('.old').html();
    var new = $(this).siblings('.new').val();

    var self = this;

    $.ajax({
        url: 'doop.php',
        type: 'POST',
        data: 'before=' + old + '&after=' + new,
        success: function(resp) {
            if(resp == 1) {
                $(self).siblings('.old').html(new);
            }
        }
    });

    return false;
}

The success function will retain the value of self when invoked, and should behave as you expected.

harto
  • 89,823
  • 9
  • 47
  • 61
  • Thanks +1. This is the same as crescentfresh's answer and it solves "part of the problem".. will update the question with more troubleshooting. – Chris Oct 15 '09 at 04:20