Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to update cached jquery object after adding elements via AJAX

I'm trying to write a plugin-like function in jQuery to add elements to a container with AJAX. It looks like this:

$.fn.cacheload = function(index) {
    var $this = $(this);
    $.get("cache.php", {{ id: index }).done(function(data) {
        // cache.php returns <div class='entry'>Content</div> ...
        $(data).insertAfter($this.last());
    });
}

and I would like to use it like this:

var entries = $("div.entry"),
    id = 28;

entries.cacheload(id);

Think that this would load another "entry"-container and add it to the DOM.

This is works so far. But of course the variable that holds the cached jQuery object (entries) isn't updated. So if there were two divs in the beginning and you would add another with this function it would show in the DOM, but entries would still reference the original two divs only.

I know you can't use the return value of get because the AJAX-call is asynchronous. But is there any way to update the cached object so it contains the elements loaded via AJAX as well?

I know I could do it like this and re-query after inserting:

    $.get("cache.php", {{ id: num }).done(function(data) {
        $(data).insertAfter($this.last());
        entries = $("div.entry");
    });

but for this I would have to reference the variable holding the cached objects directly. Is there any way around this so the function is self-contained? I tried re-assigning $(this), but got an error. .add() doesn't update the cached object, it creates a new (temporary) object.

Thanks a lot!

// UPDATE:

John S gave a really good answer below. However, I ended up realizing that for me something else would actually work better. Now the plugin function inserts a blank element (synchronously) and when the AJAX call is complete the attributes of that element are updated. That also ensures that elements are loaded in the correct order. For anyone stumbling over this, here is a JSFiddle: http://jsfiddle.net/JZsLt/2/

like image 468
pjupju Avatar asked Nov 11 '22 14:11

pjupju


1 Answers

As you said yourself, the ajax call is asynchronous. Therefore, your plugin is asynchronous as as well. There's no way for your plugin to add the new elements to the jQuery object until the ajax call returns. Plus, as you discovered, you can't really add to the original jQuery object, you can only create a new jQuery object.

What you can do is have the plugin take a callback function as a second parameter. The callback could be passed a jQuery object that contains the original elements plus the newly inserted ones.

$.fn.cacheload = function(index, callback) {
    var $this = this;
    $.get('cache.php', { id: index }).done(function(html) {
        var $elements = $(html);
        $this.last().after($elements);
        if (callback) {
            callback.call($this, $this.add($elements));
        }
    });
    return $this;
};

Then you could call:

entries.cacheload(id, function($newEntries) { doSomething($newEntries); } );

Of course, you could do this:

entries.cacheload(id, function($newEntries) { entries = $newEntries; } );

But entries will not be changed until the ajax call returns, so I don't see much value in it.

BTW: this inside a plugin refers to a jQuery object, so there's no need to call $(this).

like image 156
John S Avatar answered Nov 14 '22 22:11

John S