Take the 2-minute tour ×

I'm using the jQuery tablesorter 2.14.5. I load the table like this:

var html = '';
    // code to fill html
$('#TableToFill tbody').html(html);

if (filterlist) {
    $.tablesorter.setFilters($('#TableToFill'), filterlist, true);

And it works great when the page first loads. However I'm refreshing the contents of the table with AJAX. It reloads rows and runs this code again. When the page first loads (and filterlist does have something) then the table's contents are filtered properly. When the AJAX completes and this code runs again (filterlist containing the same thing it had before) then the table does not filter. The filter inputs have the proper values in them, but the unfiltered table contents are displayed.

What can I do differently to make sure that when the table is recreated with new values through AJAX that the filters stay applied?

EDIT: All of the code.

HTML for empty table:

<table id="ProblemQueue" class="tablesorter tablesorter_sorted" border="0" cellpadding="0" cellspacing="1" style="overflow: scroll;">
        <col span="1" style="width: 17%;">
        <col span="1" style="width: 10%;">
        <col span="1" style="width: 20%;">
        <col span="1" style="width: 5%;">
        <col span="1" style="width: 13%;">
        <col span="1" style="width: 8%;">
        <tr class="tablesorter-headerRow">
            <th>First Name</th>
            <th>Last Name</th>
            <th class="filter-select">Problem</th>
            <th class="filter-false">Note</th>
            <th class="filter-false">Action</th>
            <th>Last Worked</th>
            <th class="filter-select">User</th>
            <th>Date Recieved</th>

The only call to tablesorter:

    theme: 'blue',
    widthFixed: true, // hidden filter input/selects will resize the columns, so try to minimize the change
    widgets: ["zebra", "filter"],// initialize zebra striping and filter widgets
    headers: { 4: { sorter: false, filter: false }, 5: { sorter: false, filter: false } },
    widgetOptions: {
        filter_childRows: false,
        filter_columnFilters: true,
        filter_cssFilter: 'tablesorter-filter',
        filter_filteredRow: 'filtered',
        filter_formatter: null,
        filter_functions: null,
        filter_hideFilters: false, // true, (see note in the options section above)
        filter_ignoreCase: true,
        filter_liveSearch: true,
        filter_reset: 'button.reset',
        filter_searchDelay: 300,
        filter_serversideFiltering: false,
        filter_startsWith: false,
        filter_useParsedData: false
}).bind('filterEnd', function () {
    sessvars.filters.ProblemQueue = $.tablesorter.getFilters($('#ProblemQueue'));

The table is always filled through ajax. The above example was shortened for conciseness, but here is what the actual code looks like:

function GetProblemQueue(async) {
    async = async || true;
    var url = "/our/rest/api";
        url: url,
        dataType: "json",
        headers: { "x-li-format": "json" },
        async: async,
        cache: false,
        success: function (data) {
            problems = data; // problems is global
        type: "Get"

function FillProblemQueue() {
    var rows = '';
    for (var i = 0; i < problems.length; i++) {
        var style = "odd";
        if (i % 2) { style = "even"; }
        rows += "<tr class='" + style + "'><td>";
        // cell text added to rows, removed business logic
        rows += "</td><td>";
        rows += "</td><td style='text-align:center;'>";
        rows += "</td></tr>";
    $("#ProblemQueue tbody").html(rows);
    if (sessvars.filters.ProblemQueue) {
        $.tablesorter.setFilters($('#ProblemQueue'), sessvars.filters.ProblemQueue, true);

GetProblemQueue(true) is called on document ready and there's a setInterval that calls it every 60 seconds. This is in IE 10. It has to work for IE 10 due to business requirements.

share|improve this question
Any reason you're not using Datatables? It's got built in server side processing, and filtering and whatnot super easy. –  Tim Jan 27 at 23:09
Changing table libraries is not in our best interest right now. Besides, I do like this library. –  Corey Ogburn Jan 28 at 16:31
add comment

1 Answer

up vote 1 down vote accepted

Tablesorter should not be re-initialized after the ajax call

// this should only be done once

Instead after each ajax call, trigger an update:


The filter widget should reapply automatically, so no need to set the filters again.

Update: Oh, I understand now. Basically, the filter widget won't update its search when the filters haven't changed. It doesn't know that the table contents have been updated. So to bypass that issue, trigger a "search" on the table and include a false flag:

$('#TableToFill').trigger('search', false);

I'll fix this in the next update, so that when the setFilter function is called with the apply flag set to true, it will force a new search.

Here are a few other observations I noticed when reviewing the above code:

  • There is no need to include widget options if they are not changing the default.
  • There is no need to set the widthFixed option as it will not do anything since a <colgroup> and <col> is already defined.
  • Adding a filter: false to the headers option has priority over the "filter-false" class name in the header <th class="filter-false">. There is no need to include both, either will work.
  • With the above suggestion, triggering a search with false flag, there shouldn't be a need to use $.tablesorter.getFilter() or $.tablesorter.setFilter() functions.
share|improve this answer
After a little reworking, I only call tablesorter once, but the trigger is not updating the table. Nothing happens. I have breakpoints in a bind on filterEnd and they aren't being hit after the update and the table is not refiltering. –  Corey Ogburn Jan 28 at 6:57
Can you share more of the code you are using; it sounds like the issue might be there. –  Mottie Jan 28 at 13:55
Added to the question. Nearly cut and paste of what's actually running. Only removed some business stuff. –  Corey Ogburn Jan 28 at 16:32
Ok, try my updated suggestion. –  Mottie Jan 28 at 18:40
I'm using an interesting library called sessvars. It stores variables in window.name as sort of a client side session. The web app I'm working on will move from this page to another page, but when the user comes back to this page, it should re-filter the way the user had it before. This library is filled with the filters and is used to reapply them so as per your last bullet, it's less about making filtering work and more about maintaining multipage sessions. –  Corey Ogburn Jan 28 at 18:48
show 2 more comments

Your Answer


