HTML table sort

So basically I am running a mysql query that fetches data from my database and displays it in an easy to read layout for my users.

Name-----Address----Sales Person 

You get the gist. And now I want to let the user sort the html table by let's say sales person. How would I easily do that using a drop down menu?

<div class='menu'> <ul> <li><a href='#'><span>Sales Person</span></a> <ul> <li><a href='#'><span>Melissa</span></a></li> <li><a href='#'><span>Justin</span></a></li> <li><a href='#'><span>Judy</span></a></li> <li><a href='#'><span>Skipper</span></a></li> <li><a href='#'><span>Alex</span></a></li> </ul> </li> </ul> </div>
2

6 Answers

Check if you could go with any of the below mentioned JQuery plugins. Simply awesome and provide wide range of options to work through, and less pains to integrate. :)

- Flexgrid
- Data tables.

If not, you need to have a link to those table headers that calls a server-side script to invoke the sort.

2

Here is another library.

Changes required are -

  1. Add sorttable js

  2. Add class name sortable to table.

Click the table headers to sort the table accordingly:

<script src=""></script> <table> <tr> <th>Name</th> <th>Address</th> <th>Sales Person</th> </tr> <tr> <td>user:0001</td> <td>UK</td> <td>Melissa</td> </tr> <tr> <td>user:0002</td> <td>France</td> <td>Justin</td> </tr> <tr> <td>user:0003</td> <td>San Francisco</td> <td>Judy</td> </tr> <tr> <td>user:0004</td> <td>Canada</td> <td>Skipper</td> </tr> <tr> <td>user:0005</td> <td>Christchurch</td> <td>Alex</td> </tr> </table>
7

The way I have sorted HTML tables in the browser uses plain, unadorned Javascript.

The basic process is:

  1. add a click handler to each table header
  2. the click handler notes the index of the column to be sorted
  3. the table is converted to an array of arrays (rows and cells)
  4. that array is sorted using javascript sort function
  5. the data from the sorted array is inserted back into the HTML table

The table should, of course, be nice HTML. Something like this...

<table> <thead> <tr><th>Name</th><th>Age</th></tr> </thead> <tbody> <tr><td>Sioned</td><td>62</td></tr> <tr><td>Dylan</td><td>37</td></tr> ...etc... </tbody> </table> 

So, first adding the click handlers...

const table = document.querySelector('table'); //get the table to be sorted table.querySelectorAll('th') // get all the table header elements .forEach((element, columnNo)=>{ // add a click handler for each element.addEventListener('click', event => { sortTable(table, columnNo); //call a function which sorts the table by a given column number }) }) 

This won't work right now because the sortTable function which is called in the event handler doesn't exist.

Lets write it...

function sortTable(table, sortColumn){ // get the data from the table cells const tableBody = table.querySelector('tbody') const tableData = table2data(tableBody); // sort the extracted data tableData.sort((a, b)=>{ if(a[sortColumn] > b[sortColumn]){ return 1; } return -1; }) // put the sorted data back into the table data2table(tableBody, tableData); } 

So now we get to the meat of the problem, we need to make the functions table2data to get data out of the table, and data2table to put it back in once sorted.

Here they are ...

// this function gets data from the rows and cells // within an html tbody element function table2data(tableBody){ const tableData = []; // create the array that'll hold the data rows tableBody.querySelectorAll('tr') .forEach(row=>{ // for each table row... const rowData = []; // make an array for that row row.querySelectorAll('td') // for each cell in that row .forEach(cell=>{ rowData.push(cell.innerText); // add it to the row data }) tableData.push(rowData); // add the full row to the table data }); return tableData; } // this function puts data into an html tbody element function data2table(tableBody, tableData){ tableBody.querySelectorAll('tr') // for each table row... .forEach((row, i)=>{ const rowData = tableData[i]; // get the array for the row data row.querySelectorAll('td') // for each table cell ... .forEach((cell, j)=>{ cell.innerText = rowData[j]; // put the appropriate array element into the cell }) }); } 

And that should do it.

A couple of things that you may wish to add (or reasons why you may wish to use an off the shelf solution): An option to change the direction and type of sort i.e. you may wish to sort some columns numerically ("10" > "2" is false because they're strings, probably not what you want). The ability to mark a column as sorted. Some kind of data validation.

2

Another approach to sort HTML table. (based on W3.JS HTML Sort)

let tid = "#usersTable"; let headers = document.querySelectorAll(tid + " th"); // Sort the table element when clicking on the table headers headers.forEach(function(element, i) { element.addEventListener("click", function() { w3.sortHTML(tid, ".item", "td:nth-child(" + (i + 1) + ")"); }); });
th { cursor: pointer; background-color: coral; }
<script src=""></script> <link href="" rel="stylesheet" /> <p>Click the <strong>table headers</strong> to sort the table accordingly:</p> <table> <!-- <tr> <th onclick="w3.sortHTML('#usersTable', '.item', 'td:nth-child(1)')">Name</th> <th onclick="w3.sortHTML('#usersTable', '.item', 'td:nth-child(2)')">Address</th> <th onclick="w3.sortHTML('#usersTable', '.item', 'td:nth-child(3)')">Sales Person</th> </tr> --> <tr> <th>Name</th> <th>Address</th> <th>Sales Person</th> </tr> <tr> <td>user:2911002</td> <td>UK</td> <td>Melissa</td> </tr> <tr> <td>user:2201002</td> <td>France</td> <td>Justin</td> </tr> <tr> <td>user:2901092</td> <td>San Francisco</td> <td>Judy</td> </tr> <tr> <td>user:2801002</td> <td>Canada</td> <td>Skipper</td> </tr> <tr> <td>user:2901009</td> <td>Christchurch</td> <td>Alex</td> </tr> </table>
4

Found some way to do that with multiple tables and different data types, without external libraries.

Steps:

  1. Add event listeners to all table headers.
  2. Find the table related to the clicked header and get the order icon.
  3. Declare an object to store the table rows(tr) and an array of values of the selected column.
  4. Iterate the values and check the data type for future sorting.
  5. Sort values and change the table header(th) icon.
  6. Replace the old tbody with the ordered html.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <table> <thead> <tr> <th>Coluna 1 <span>&uarr;</span></th> <th>Coluna 2 <span>&uarr;</span></th> <th>Coluna 3 <span>&uarr;</span></th> <th>Coluna 4 <span>&uarr;</span></th> <th>Coluna 5 <span>&uarr;</span></th> </tr> </thead> <tbody> <tr> <td>100</td> <td>Nome do produto 22</td> <td>ABCASD</td> <td>22DDS</td> <td>454645</td> </tr> <tr> <td>99</td> <td>Nome do produto 12</td> <td>AACASD</td> <td>22DDS</td> <td>354645</td> </tr> <tr> <td>300</td> <td>Nome do produto 22</td> <td>AcCASD</td> <td>32DDS</td> <td>554649</td> </tr> <tr> <td>400</td> <td>Nomde do produto 22</td> <td>AcdCASD</td> <td>3d2DDS</td> <td>554645</td> </tr> <tr> <td>10</td> <td>Nome do produto 1</td> <td>cCASD</td> <td>DDS</td> <td>4645</td> </tr> </tbody> </table> <br> <table> <thead> <tr> <th>Coluna 1 <span>&uarr;</span></th> <th>Coluna 2 <span>&uarr;</span></th> <th>Coluna 3 <span>&uarr;</span></th> <th>Coluna 4 <span>&uarr;</span></th> <th>Coluna 5 <span>&uarr;</span></th> </tr> </thead> <tbody> <tr> <td>100</td> <td>Nome do produto 22</td> <td>ABCASD</td> <td>22DDS</td> <td>454645</td> </tr> <tr> <td>99</td> <td>Nome do produto 12</td> <td>AACASD</td> <td>22DDS</td> <td>354645</td> </tr> <tr> <td>300</td> <td>Nome do produto 22</td> <td>AcCASD</td> <td>32DDS</td> <td>554649</td> </tr> <tr> <td>400</td> <td>Nomde do produto 22</td> <td>AcdCASD</td> <td>3d2DDS</td> <td>554645</td> </tr> <tr> <td>10</td> <td>Nome do produto 1</td> <td>cCASD</td> <td>DDS</td> <td>4645</td> </tr> </tbody> </table> <script> window.onload = function () { // After page loads Array.from(document.getElementsByTagName("th")).forEach((element, index) => { // Table headers element.addEventListener("click", function (event) { let table = this.closest("table"); let order_icon = this.getElementsByTagName("span")[0]; let order = encodeURI(order_icon.innerHTML).includes("%E2%86%91") ? "desc" : "asc"; let value_list = {}; // <tr> Object let obj_key = []; // Values of selected column let string_count = 0; let number_count = 0; table.querySelectorAll("tbody tr").forEach((linha, index_line) => { // <tbody> rows let key = linha.children[element.cellIndex].innerHTML.toUpperCase(); key.replace("-", "").match(/^[0-9,.]*$/g) ? number_count++ : string_count++; // Check if value is numeric or string value_list[key + index_line] = linha.outerHTML; // Adding <tr> to object obj_key.push(key + index_line); }); if (number_count > 0 && string_count <= 0) { // If all values are numeric obj_key.sort(function(a, b) { return a - b; }); } else { obj_key.sort(); } if (order == "desc"){ obj_key.reverse(); order_icon.innerHTML = "&darr;"; } else { order_icon.innerHTML = "&uarr;"; } let html = ""; obj_key.forEach(function (chave) { html += value_list[chave]; }); table.getElementsByTagName("tbody")[0].innerHTML = html; }); }); } </script> </body> </html>

Flexbox-based tables can easily be sorted by using flexbox property "order".

Here's an example:

function sortTable() { let table = document.querySelector("#table") let children = [...table.children] let sortedArr = children.map(e => e.innerText).sort((a, b) => a.localeCompare(b)); children.forEach(child => { child.style.order = sortedArr.indexOf(child.innerText) }) } document.querySelector("#sort").addEventListener("click", sortTable)
#table { display: flex; flex-direction: column }
<div> <div>Melissa</div> <div>Justin</div> <div>Judy</div> <div>Skipper</div> <div>Alex</div> </div> <button> sort </button>

Explanation

The sortTable function extracts the data of the table into an array, which is then sorted in alphabetic order. After that we loop through the table items and assign the CSS property order equal to index of an item's data in our sorted array.

2

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

You Might Also Like