Sorting HTML Table with JavaScript

Sorting HTML table with JavaScript

Just revisiting an old solution, I thought I'd give it a facelift for it's ~5 year anniversary!

  • Plain Javascript (ES6)
  • Does alpha and numeric sorting - ascending and descending
  • Works in Chrome, Firefox, Safari (and IE11, see below)

Quick explanation

  1. add a click event to all header (th) cells...
  2. for the current table, find all rows (except the first)...
  3. sort the rows, based on the value of the clicked column...
  4. insert the rows back into the table, in the new order.

const getCellValue = (tr, idx) => tr.children[idx].innerText || tr.children[idx].textContent;

const comparer = (idx, asc) => (a, b) => ((v1, v2) =>
v1 !== '' && v2 !== '' && !isNaN(v1) && !isNaN(v2) ? v1 - v2 : v1.toString().localeCompare(v2)
)(getCellValue(asc ? a : b, idx), getCellValue(asc ? b : a, idx));

// do the work...
document.querySelectorAll('th').forEach(th => th.addEventListener('click', (() => {
const table = th.closest('table');
Array.from(table.querySelectorAll('tr:nth-child(n+2)'))
.sort(comparer(Array.from(th.parentNode.children).indexOf(th), this.asc = !this.asc))
.forEach(tr => table.appendChild(tr) );
})));
table, th, td {
border: 1px solid black;
}
th {
cursor: pointer;
}
<table>
<tr><th>Country</th><th>Date</th><th>Size</th></tr>
<tr><td>France</td><td>2001-01-01</td><td><i>25</i></td></tr>
<tr><td><a href=#>spain</a></td><td><i>2005-05-05</i></td><td></td></tr>
<tr><td><b>Lebanon</b></td><td><a href=#>2002-02-02</a></td><td><b>-17</b></td></tr>
<tr><td><i>Argentina</i></td><td>2005-04-04</td><td><a href=#>100</a></td></tr>
<tr><td>USA</td><td></td><td>-6</td></tr>
</table>

Sorting a HTML table with Array#sort

You can use Array.from to get the td elements in an array that can be sorted. Then add each of them again to the table in that order. This will be understood as a move in the DOM, so you'll end up with sorted table rows:

let table = document.getElementById("table1");
let trs = table.rows;

Array.from(trs)
.sort((a, b) => a.cells[0].textContent - b.cells[0].textContent)
.forEach(tr => table.appendChild(tr));
<table id="table1">
<tr><td>2</td></tr>
<tr><td>4</td></tr>
<tr><td>3</td></tr>
<tr><td>1</td></tr>
</table>

Sorting a table in JavaScript - hiding table rows with no subsequent rows

This is my Vanilla JavaScript take on it.

Before writing the script I changed all name attributes to data-name as trs cannot have name attributes "legally".

In a first filter() loop I make all trs invisible and filter out only those trs that don't match the given pattern pat and are not of class "header". In a forEach() loop applied on this filtered set I then make only those trs visible again that either themselves have a dataset.name attribute or whose direct successor has this attribute.

const trs=[...document.querySelector("#myTable>tbody").children];
function fltTbl(pat){
trs
.filter(tr=>(tr.style.display="none",tr.classList.contains("header")||
tr.dataset?.name.indexOf(pat)>-1))
.forEach((tr,i,a)=>{
if (tr.dataset.name
|| a[i+1]?.dataset.name)
tr.style.display="";
});
}
<button class="btn" onclick="fltTbl('policy-outcomes')">Policy Outcomes</button>
<button class="btn" onclick="fltTbl('latin_america')">Latin America</button>
<button class="btn" onclick="fltTbl('deforestation')">Deforestation</button>

<table class="mytable" id="myTable">
<tr class="header">
<th style="width:60%;">2020</th>
</tr>
<tr data-name="latin_america_zero-deforestation">
<td>"Cattle Ranchers and Deforestation.”
</td>
</tr>
<tr data-name="latin_america_policy-outcomes">
<td>“Impacts on Land Use Conversion.”
</td>
</tr>
<tr data-name="latin_america_supply-chain_policy-outcomes">
<td>“Costs of the Amazon Soy Moratorium.”
</td>
</tr>
<tr class="header">
<th style="width:60%;">2019</th>
</tr>
<tr data-name="africa_policy-outcomes">
<td>“Environmental Change”
</td>
</tr>
<tr data-name="latin_america_policy-outcomes">
<td>“Land Use Change”
</td>
</tr>
<tr class="header">
<th style="width:60%;">2018</th>
</tr>
<tr data-name="north_america_zero-deforestation">
<td>“Deforestation Remedies”
</td>
</tr>
<tr data-name="latin_america_zero-deforestation">
<td>“Land Use Change in Latin American Cerrados”
</td>
</tr>
</table>

How do I make a custom 'sort by' in HTML Table?

You could code it from scratch using JavaScript or use a plugin like this: https://datatables.net/



Related Topics



Leave a reply



Submit