13

I have some jQuery that is triggered on click of a link with the class 'changetag'. I'm using $.ajax() to update the database via changetag.php.

I then change the visual appearance of the link by toggling the class between on/off. The code is as follows:

$(function() {
$(".changetag").click(function(){
    var element = $(this);
    var I = element.attr("id");
    var info = 'switch_tag=' + I;

    $.ajax({
        type: "POST",
        url: "_js/changetag.php",
        data: info,
        success: function(){}
    });

    $("#li_"+I).toggleClass("off on");
    element.toggleClass("off on");

    return false;
});
});

Works perfectly. But now I want to add in a second PHP call which will pull data and update another area of the page if the above was successful.

What I'm trying to add is:

$.ajax({
    url: "_js/loaddata.php",
    success: function(results){
        $('#listresults').empty();
        $('#listresults').append(results);
    }
});

But just adding it into success: function(){} doesn't seem to be working. To clarify, here is the complete code I'm testing:

$(function() {
$.ajaxSetup ({cache: false});
$(".changetag").click(function(){
    var element = $(this);
    var I = element.attr("id");
    var info = 'switch_tag=' + I;

    $.ajax({
        type: "POST",
        url: "_js/changetag.php",
        data: info,
        success: function(){
            $.ajax({
                url: "_js/loaddata.php",
                success: function(results){
                    $('#listresults').empty();
                    $('#listresults').append(results);
                }
            });
        }
    });

    $("#li_"+I).toggleClass("off on");
    element.toggleClass("off on");

    return false;
});
});

The PHP scripts are both called successfully and the toggle class works, but the data pulled is not written to #listresults for some reason.

Matt Ball
  • 354,903
  • 100
  • 647
  • 710
Paul
  • 661
  • 4
  • 12
  • 22
  • how is it not working? are you getting an error? is your result variable returning data? – Patrick Mar 30 '11 at 13:28
  • 1
    Try chaining them - $.ajax({}).ajax({}); – Elad Lachmi Mar 30 '11 at 13:29
  • @partick @elad-lachmi actually both calls seem to be successful, I think its just the $('#listresults').empty(); and $('#listresults').append(results); that is failing to update the page – Paul Mar 30 '11 at 13:36
  • 1
    Is results an html string? I believe append needs to take a DOM element, html string, etc. It can't take just any type of content. – McStretch Mar 30 '11 at 13:51
  • There's no reason to `.empty()` and then `.append()`. Just do `$('#listresults').html(results);` – Matt Ball Mar 30 '11 at 13:56

2 Answers2

25

Ajax calls are (by default) asynchronous. That means that this code:

$("#li_"+I).toggleClass("off on");
element.toggleClass("off on");

return false;

could be executed before the ajax call preceding it is finished. This is a common problem for programmers who are new to ajax and asynchronous code execution. Anything you want to be executed after the ajax call is done must be put into a callback, such as your success handler:

$.ajax({
    type: "POST",
    url: "_js/changetag.php",
    data: info,
    success: function(){
        $("#li_"+I).toggleClass("off on");
        element.toggleClass("off on");
    }
});

Likewise, you could put the second ajax call in there as well:

$.ajax({
    type: "POST",
    url: "_js/changetag.php",
    data: info,
    success: function(){
        $("#li_"+I).toggleClass("off on");
        element.toggleClass("off on");

        $.ajax({
            url: "_js/loaddeals_v2.php",
            success: function(results){
                $('#listresults').empty();
                $('#listresults').append(results);
            }
        });
    }
});

With jQuery 1.5's Deferred Object, you can make this slicker.

function firstAjax() {
    return $.ajax({
        type: "POST",
        url: "_js/changetag.php",
        data: info,
        success: function(){
            $("#li_"+I).toggleClass("off on");
            element.toggleClass("off on");
        }
    });
}

// you can simplify this second call and just use $.get()
function secondAjax() {
    return $.get("_js/loaddata.php", function(results){
        $('#listresults').html(results);
    });
}

// do the actual ajax calls
firstAjax().success(secondAjax);

This is nice because it lets you un-nest callbacks - you can write code that executes asynchronously, but is written like synchronously-executed code.

Matt Ball
  • 354,903
  • 100
  • 647
  • 710
0

Deprecation Notice: The jqXHR.success(), jqXHR.error(), and jqXHR.complete() callbacks are removed as of jQuery 3.0. You can use jqXHR.done(), jqXHR.fail(), and jqXHR.always() instead. https://api.jquery.com/jQuery.ajax/#jqXHR

Community
  • 1
  • 1
Patrick D
  • 91
  • 1
  • 4