jQuery tablesorter - loss of functionality after AJAX call
Asked Answered
Z

8

11

I have recently been experimenting with the tablesorter plugin for jQuery. I have successfully got it up and running in once instance, and am very impressed. However, I have tried to apply the tablesorter to a different table, only to encounter some difficulties...

Basically the table causing a problem has a <ul> above it which acts as a set of tabs for the table. so if you click one of these tabs, an AJAX call is made and the table is repopulated with the rows relevant to the specific tab clicked. When the page initially loads (i.e. before a tab has been clicked) the tablesorter functionality works exactly as expected.

But when a tab is clicked and the table repopulated, the functionality disappears, rendering it without the sortable feature. Even if you go back to the original tab, after clicking another, the functionality does not return - the only way to do so is a physical refresh of the page in the browser.

I have seen a solution which seems similar to my problem on this site, and someone recommends using the jQuery plugin, livequery. I have tried this but to no avail :-(

If someone has any suggestions I would be most appreciative. I can post code snippets if it would help (though I know the instantiation code for tablesorter is fine as it works on tables with no tabs - so it's definitely not that!)

EDIT: As requested, here are some code snippets:
The table being sorted is <table id="#sortableTable#">..</table>, the instantiation code for tablesorter I am using is:

$(document).ready(function() 
{ 
    $("#sortableTable").tablesorter(
    {
        headers: //disable any headers not worthy of sorting!
        {
            0: { sorter: false },
            5: { sorter: false }
        },
        sortMultiSortKey: 'ctrlKey',
        debug:true,
        widgets: ['zebra']
    }); 
});

And I tried to rig up livequery as follows:

$("#sortableTable").livequery(function(){
   $(this).tablesorter();
});

This has not helped though... I am not sure whether I should use the id of the table with livequery as it is the click on the <ul> I should be responding to, which is of course not part of the table itself. I have tried a number of variations in the hope that one of them will help, but to no avail :-(

Zygodactyl answered 18/2, 2009 at 11:23 Comment(0)
C
23

Once you have appended your data, do this:

$("your-table").trigger("update"); 
var sorting = [[0,0]]; 
$("your-table").trigger("sorton",[sorting]);

This will let the plugin know it has had an update, and re-sort it.

The complete example given in the doc:

$(document).ready(function() { 
    $("table").tablesorter(); 
    $("#ajax-append").click(function() { 
         $.get("assets/ajax-content.html", function(html) { 
             // append the "ajax'd" data to the table body 
             $("table tbody").append(html); 
            // let the plugin know that we made a update 
            $("table").trigger("update"); 
            // set sorting column and direction, this will sort on the first and third column 
            var sorting = [[2,1],[0,0]]; 
            // sort on the first column 
            $("table").trigger("sorton",[sorting]); 
        }); 
        return false; 
    }); 
});

From the tablesorter doc here: http://tablesorter.com/docs/example-ajax.html

Copolymerize answered 23/12, 2009 at 2:15 Comment(1)
Just came across this. .trigger() worked so much better than calling .tablesorter() again. Thanks!Condon
M
4

Have you tried calling

$("#myTable").tablesorter();

after the code where you handle the click on tab and repopulate the table??? If not, just give it a try.

Matronymic answered 18/2, 2009 at 11:55 Comment(2)
try the trigger() method as suggested by elwyn, much more efficient than reinitializing the entire table.Jany
Thanks..Grt answer..Worked for me.Cassondra
T
3

It may be that as your second table is created with ajax that you need to rebind the events. You may want to use the LiveQuery plugin

http://docs.jquery.com/Plugins/livequery

which might "auto-magically" help with your problem.

edit: sorry, just reread your post and seen that you've tried that already.


Update. I've rigged up a quick test harness which hopefully will help. There are 3 LIs at the top each one has a different way of updating the table contents. The last one updates the contents and keeps the ordering

    <script src="jquery-1.3.js"  type="text/javascript" ></script>
    <script src="jquery.livequery.js"  type="text/javascript" ></script>
    <script src="jquery.tablesorter.min.js" type="text/javascript" ></script>

<script>

var newTableContents = "<thead><tr><th>Last Name</th><th>First Name</th>
<th>Email</th><th>Due</th><th>Web Site</th></tr></thead>
<tbody><tr><td>Smith</td><td>John</td><td>[email protected]</td><td>$50.00</td>
    <td>http://www.jsmith.com</td></tr><tr><td>Bach</td><td>Frank</td><td>[email protected]</td>
<td>$50.00</td><td>http://www.frank.com</td></tr></tbody>";


 $(document).ready(function() 
    { 
        $("#addData").click(function(event){
        $("#sortableTable").html(newTableContents);
    });

    $("#addLivequery").livequery("click", function(event){
        $("#sortableTable").html(newTableContents);
    });

    $("#addLiveTable").livequery("click", function(event){
        $("#sortableTable").html(newTableContents);
        $("#sortableTable").tablesorter( { } ); 
    });

    $("#sortableTable").tablesorter( { } ); 
  });
</script>

        <ul>
            <li id="addData" style="background-color:#ffcc99;display:inline;">Update Table</li>
            <li id="addLivequery" style="background-color:#99ccff;display:inline;">Update Table with livequery</li>
            <li id="addLiveTable" style="background-color:#99cc99;display:inline;">Update Table with livequery & tablesorter</li> 
        </ul>

        <hr />
        <table id="sortableTable"> 
        <thead> 
        <tr> 
            <th>Last Name</th> 
            <th>First Name</th> 
            <th>Email</th> 
            <th>Due</th> 
            <th>Web Site</th> 
        </tr> 
        </thead> 
        <tbody> 
        <tr> 
            <td>Jones</td> 
            <td>Joe</td> 
            <td>[email protected]</td> 
            <td>$100.00</td> 
            <td>http://www.jjones.com</td> 
        </tr> 
        <tr> 
            <td>French</td> 
            <td>Guy</td> 
            <td>[email protected]</td> 
            <td>$50.00</td> 
            <td>http://www.french.com</td> 
        </tr> 
        </tbody> 
        </table> 
Troubadour answered 18/2, 2009 at 12:12 Comment(7)
yeah i did try this, but i'm not experienced with jQuery and certainly not livequery... maybe i did it wrong?Zygodactyl
I'm not that experienced with JQuery and livequery myself but I had a problem that it fixed yesterday. If you post up some code snippet I'll see if I can see anything that helps.Troubadour
have added snippets in my original postZygodactyl
have added a test harness which might help you.Troubadour
thanks, i'll have a good look into this now. let you know how i get onZygodactyl
:-( although the example you gave proves that it shoudl work, it doesn't when i implement it in my code. perhaps something to do with the microsoft mvc framework we're using?Zygodactyl
oh well. Good luck in finding a solution. If i think of anything else that might help i'll post it up.Troubadour
D
1

Use the ajaxStop function and the code will run after the ajax call is complete.

$("#DivBeingUpdated").ajaxStop(function(){ 
    $("table").tablesorter()
});
Decoder answered 11/2, 2012 at 19:0 Comment(0)
Z
0

Turns out I had to make some modifications to the AJAX related code to re-call $("#myTable").tablesorter(..) after pulling any data...

Zygodactyl answered 19/2, 2009 at 11:17 Comment(0)
R
0

I was having the same problem except I was loading a table that had a row for every 'category' then inserting the data for every category into the table using asynchronous calls. Calling $("#myTable").tablesorter(..) after each record was returned caused my browser to bomb when more than a trivial number of records were loaded.

My solution was to declare two variables, totalRecords and fetchedRecords. In the $(document).ready() I set the totalRecords to $("#recordRows").length; and every time I populate a record in the table, the fetchedRecords variable is incremented and if fetchedRecords >= totalRecords then I call $("#myTable").tableSorter(..).

Works quite well for me. Of course, your mileage may vary.

Rohrer answered 9/6, 2009 at 17:0 Comment(0)
E
0

after ajax call when changed your html content you need to update TableSorter.

TRY THIS FOR ME WORKING OK

if you appending html

$("table tbody").append(html); 
        // let the plugin know that we made a update 
        $("table").trigger("update"); 
        // set sorting column and direction, this will sort on the first and third column 
        var sorting = [[2,1],[0,0]]; 
        // sort on the first column 
        $("table").trigger("sorton",[sorting]);

and when you add new html instead older

$("table").trigger("update");
$("table").trigger("sorton");
Eventide answered 22/12, 2015 at 15:18 Comment(0)
D
0

I've come across this problem recently. elwyn's solution didn't work for me. But this topic suggested that the problem is in synchronization of functions on "update" and "sorton" events.

If you look in the code of jQuery Tablesorter 2.0 (ver. 2.0.5b) source code, you'll see something like:

$this.bind("update", function () {
    var me = this;
    setTimeout(function () {
        // rebuild parsers.
        me.config.parsers = buildParserCache(me, $headers);
        // rebuild the cache map
        cache = buildCache(me);
    }, 1);
}).bind("sorton", function (e, list) {
    $(this).trigger("sortStart");
    config.sortList = list;
    // update and store the sortlist
    var sortList = config.sortList;
    // update header count index
    updateHeaderSortCount(this, sortList);
    // set css for headers
    setHeadersCss(this, $headers, sortList, sortCSS);
    // sort the table and append it to the dom
    appendToTable(this, multisort(this, sortList, cache));
});

So the problem is that setTimeout makes it less probable that update will be finished before sorting. My solution was to implement yet another event "updateSort", so that above code would become:

var updateFunc = function (me) {
    me.config.parsers = buildParserCache(me, $headers);
    cache = buildCache(me);
};
var sortFunc = function (me, e, list) {
    $(me).trigger("sortStart");
    config.sortList = list;
    var sortList = config.sortList;
    updateHeaderSortCount(me, sortList);
    setHeadersCss(me, $headers, sortList, sortCSS);
    appendToTable(me, multisort(me, sortList, cache));
};
$this.bind("update", function () {
    var me = this;
    setTimeout(updateFunc(me), 1);
}).bind("sorton", function(e, list) {
    var me = this;
    sortFunc(me, e, list);
}).bind("updateSort", function (e, list) {
    var me = this;
    updateFunc(me);
    sortFunc(me, e, list);
});

After updating data in your table you would have to trigger only this new event:

var sorting = [[0,0]]; 
$("#your-table").trigger("updateSort",[sorting]);
Duggan answered 4/3, 2017 at 8:25 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.