Skip to content

Sort rows in table

I’m trying to sort rows in alphabetical order based on which column header is clicked using jQuery. It works fairly fine when debugging except that it doesn’t actually switch the rows in the HTML and so it doesn’t display a sorted table on the webpage. I’m using Thymeleaf th:text to populate the table body rows but for the sake of this example, I hardcoded some values. You can run it here: https://jsfiddle.net/tg2khrd4

Javascript:

var table = $("#table");

$("#subject, #from, #id")
  .wrapInner('<span title="sort this column"/>')
  .each(function () {
    var th = $(this),
      thIndex = th.index(),
      inverse = false;

    th.click(function () {
      table
        .find("tbody")
        .find("td")
        .filter(function () {
          return $(this).index() === thIndex;
        })
        .sort(
          function (a, b) {
            return $.text([a]) > $.text([b])
              ? inverse
                ? -1
                : 1
              : inverse
              ? 1
              : -1;
          },
          function () {
            // parentNode is the element we want to move
            return this.parentNode;
          }
        );

      inverse = !inverse;
    });
  });

HTML:

<table class="table table-hover" id="table" style="background-color:#fff;border: 1px solid #cccccc">
  <thead style="background-color:#981e32;">
    <tr>
      <td class="tdsubj" id="id" style="padding:5px;">Id
      </td>
      <td class="tdsubj" id="subject" style="padding:5px;">
        Subject
      </td>
      <td class="tdsubj" id="from" style="padding:5px;">
        From
      </td>
      <td class="tdsubj" id="date" style="padding:5px;">
        Date
      </td>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>1</td>
      <td>Hello</td>
      <td>Thor</td>
      <td>2020-10-19</td>
    </tr>
    <tr>
      <td>2</td>
      <td>Dinos Suck</td>
      <td>Meteor</td>
      <td>2020-9-5</td>
    </tr>
    <tr>
      <td>3</td>
      <td>Big Ben won't stop ringing</td>
      <td>The Queen</td>
      <td>2020-8-19</td>
    </tr>
  </tbody>
</table>

Answer

Once the td sorted… You just have to loop throught it and append it’s parent tr in the table…

var table = $("#table");

$("#subject, #from, #id")
  // .wrapInner('<span title="sort this column"/>')
  .each(function () {
    var th = $(this),
      thIndex = th.index(),
      inverse = false;
      

    th.click(function () {
      let test = table
        .find("tbody")
        .find("td")
        .filter(function () {
          return $(this).index() === thIndex;
        })
        .sort(
          function (a, b) {
            return $.text([a]) > $.text([b])
              ? inverse
                ? -1
                : 1
              : inverse
              ? 1
              : -1;
          }

          // That is useless...
          /*function () {
                // parentNode is the element we want to move
                console.log(this.parentNode)
                return this.parentNode;
              }*/
        );

      // Added to demonstrate the sorting works
      console.clear()
      test.each(function () {
        console.log(this.innerText);
      });

      // Now to apply the sorting on the DOM
      // Find the tr containing it and append it to the table.
      test.each(function () {
        table.append($(this).parent("tr"))
      });

      inverse = !inverse;
    });
  });
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table class="table table-hover" id="table" style="background-color:#fff;border: 1px solid #cccccc">
      <thead style="background-color:#981e32;">
        <tr>
          <td class="tdsubj" id="id" style="padding:5px;">Id
          </td>
          <td class="tdsubj" id="subject" style="padding:5px;">
            Subject
          </td>
          <td class="tdsubj" id="from" style="padding:5px;">
            From
          </td>
          <td class="tdsubj" id="date" style="padding:5px;">
            Date
          </td>
        </tr>
      </thead>
      <tbody>
        <tr>
          <td>1</td>
          <td>Hello</td>
          <td>Thor</td>
          <td>2020-10-19</td>
        </tr>
        <tr>
          <td>2</td>
          <td>Dinos Suck</td>
          <td>Meteor</td>
          <td>2020-9-5</td>
        </tr>
        <tr>
          <td>3</td>
          <td>Big Ben won't stop ringing</td>
          <td>The Queen</td>
          <td>2020-8-19</td>
        </tr>
      </tbody>
    </table>