Search code examples
jquerytablesorter

jQuery table sorter broken on dynamically built tables


I need to build my table dynamically but sorting it is also a requirement.

I've had tablesorter working on many other tables, but those are static ones. I cannot get it to work on a dynamically built table using data received by Ajax. AFAIK you need to use $('myTable').trigger('updateAll'); after modifying the data and that is confirmed by the maintainer of the tablesorter fork that I am using.

I've built a small demo on JSFiddle.

Any ideas on how I can get this to sort dynamic tables or is it a bug? I'm using the latest release of the tablesorter plugin and jQuery 1.10.1.

EDITS:
1) I've also tried calling $('myTable').trigger('destroy'); and then re-initialising it in replace of using the above updateAll.
2) I also tried waiting till after I had built the table to initialise the tablesorter plugin on it.


Solution

  • As @T.Shah stated, in the thead, the th's are added outside of the tr. This is happening because the th's are being appended to the thead and not the tr in this code:

    tblHead.append('<th>...</th>');
    

    Change the build table code on these lines to make it work (demo):

    // Begin the row
    var html = '<tr>';
    
    // Fill the table header (thead) row
    for (var i = 0; headerColumns.length - 1 >= i; i++) {
      var id = headerColumns[i]['id'];
      var value = headerColumns[i]['value'];
    
      // Check to see if this column has an average avalible for it
      if (averages[id]) {
        value = 'Average: ' + averages[id] + '<br />' + value;
      }
    
      // Write the table head data
      html += '<th id="' + id + '"' + '>' + value + '</th>';
    }
    
    // End the row
    tblHead.append(html + '</tr>');
    

    In the <tbody>, the HTML for adding a row is incorrect, it should end with a </tr>

    tblBody.append('<tr id="tblRow' + key + '"></td>');
    

    Instead, use a string to build the row:

    html = "";
    // Fill the table body (tbody) with all required rows of data
    for (var key in reportData) {
      // Some object properties are inherited, we don't want these
      if (!reportData.hasOwnProperty(key)) {
        continue;
      }
    
      // Create a new table body row
      html += '<tr id="tblRow' + key + '">';
    
      // Apply data to each column in the row
      for (var i = 0; reportData[key].length - 1 >= i; i++) {
        var id = reportData[key][i]['id'];
        var value = reportData[key][i]['value'];
    
        // Write the column data
        html += '<td id="' + id + '"' + '>' + value + '</td>';
      }
      html += '</tr>';
    }
    tblBody.append(html);
    

    Then trigger an "updateAll".

    The reason a string is used to build the HTML is because it is better to interact with the DOM as little as possible to get the best performance. Instead of appending each element, build a HTML string and add it once, or twice in this example - once for the thead and once for the tbody.