HTML Table Sort

HTML table sort

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. :)

https://github.com/paulopmx/Flexigrid - Flexgrid

http://datatables.net/index - Data tables.

https://github.com/tonytomov/jqGrid

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

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, which has inputs in it's td

For completeness, the solution given via comment was to use a plugin. Loosely cited from DataTables.net:

Example: Live DOM ordering

... Use information available in the DOM to order columns.
Typically DataTables will read information to be ordered during its initialisation phase.
This will not be updated based on user interaction.
So ordering on columns with inputs may not reflect the current value of the inputs.

Getting current values

You must update the data that DataTables will order on, just prior to the order.
This method is much more efficient than actually ordering using the DOM, since only one DOM query is needed for each cell to be ordered.

Docs: Sorting plug-ins – Custom data source sorting

Allows complete control of the data that is to be sorted. Typically this is used to retrieve data live from the DOM just prior to the table being sorted, to perform sorting on data that can be updated by the end-user or by some other script.

Predefined data extractors

  • <input type=text> as string
  • <input type=text> as numeric
  • <input type=select> as string
  • <input type=checkbox> as boolean

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>

How to sort table in HTML by number

Something like this would do the job (without using any libraries):

const tb=document.getElementById("homes"),
trs=[...tb.children];

document.body.onclick=ev=>{
let col= ev.target.dataset?.col;
if(col){
trs.sort((a,b)=>a.children[col].textContent-b.children[col].textContent);
trs.forEach(tr=>tb.append(tr));
}
}
<button data-col="1">sort by number</button>
<button data-col="2">sort by batting order</button>
<table class='table table-hover table-dark table-bordered sortable'>
<thead>
<tr>
<!-- <th>Picture</th> -->
<th>Name</th>
<th>Number</th>
<th>Batting Order</th>
<th>Action</th>
</tr>
</thead>
<tbody id="homes">
<tr>
<td>Harry</td>
<td>23</td>
<td>10</td>
<td>go</td>
</tr>
<tr>
<td>Sally</td>
<td>56</td>
<td>1</td>
<td>stop</td>
</tr>
<tr>
<td>Tony</td>
<td>11</td>
<td>2</td>
<td>wait</td>
</tr>
</tbody>
</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>


Related Topics



Leave a reply



Submit