Welcome to a tutorial on how to create a simple sortable table with Javascript. So you have an array or HTML table that needs some sortable action? Sadly, there is no way we can do it with just pure HTML. We need to define data arrays and do array sorting in Javascript instead – This guide will walk you through the exact steps on how to do it, read on to find out!
ⓘ I have included a zip file with all the example source code at the start of this tutorial, so you don’t have to copy-paste everything… Or if you just want to dive straight in.
TABLE OF CONTENTS
DOWNLOAD & DEMO
Firstly, here is the download link to the example code as promised.
QUICK NOTES
If you spot a bug, feel free to comment below. I try to answer short questions too, but it is one person versus the entire world… If you need answers urgently, please check out my list of websites to get help with programming.
EXAMPLE CODE DOWNLOAD
Click here to download the source code, I have released it under the MIT license, so feel free to build on top of it or use it in your own project.
QUICKSTART & DEMO
SORTABLE TABLE ON AN EXISTING TABLE
<!-- (A) JS + CSS -->
<link rel="stylesheet" href="sorta.css">
<script src="sorta.js"></script>
<!-- (B) TABLE : NEEDS PROPER THEAD/TBODY -->
<table id="demoA">
<thead>
<tr>
<td>Fruit</td>
<td>Color</td>
</tr>
</thead>
<tbody>
<tr>
<td>Durian</td>
<td>Green</td>
</tr>
<tr>
<td>Orange</td>
<td>Orange</td>
</tr>
<tr>
<td>Apple</td>
<td>Red</td>
</tr>
<tr>
<td>Grape</td>
<td>Red</td>
</tr>
<tr>
<td>Blueberry</td>
<td>Blue</td>
</tr>
<tr>
<td>Pear</td>
<td>Green</td>
</tr>
</tbody>
</table>
<!-- (C) INITIALIZE -->
<script>
sorta(document.getElementById("demoA"));
</script>
Fruit | Color |
Durian | Green |
Orange | Orange |
Apple | Red |
Grape | Red |
Blueberry | Blue |
Pear | Green |
- Load the Javascript
sorta.js
, the CSS is not essential. - Create your HTML table as usual. Just make sure that it has a proper
<thead>
and<tbody>
section. - Call
sorta(HTML TABLE)
to turn it into a sortable table.
SORTABLE TABLE WITH OBJECT DATA
<!-- (B) EMPTY TABLE -->
<table id="demoB"></table>
<!-- (C) INITIALIZE -->
<script>
sorta(document.getElementById("demoB"), {
ID : [44, 11, 7, 5, 2],
Name : ["John Doe", "Jane Doe", "Aaron Doe", "Zoe Doe", "Derrick Doe"],
Color : ["Red", "Green", "Blue", "White", "Red"]
});
</script>
Yes, it’s the same sorta()
, except that we pass in an object data in the second parameter.
P.S. The object must be in the format of { HEAD : [ROWS], HEAD : [ROWS], ETC... }
SORTABLE TABLE JAVASCRIPT
With that, let us now get into more details of how the sortable table work in this section – This is for you guys who want to “deep customize” it.
PART 1) ADDING FLAGS TO THE TABLE
function sorta (instance, data) {
// (A) ATTACH FLAGS TO TABLE
instance.sBy = null; // sort by this field
instance.sDirection = true; // ascending/descending
instance.sOrder = []; // calculated sort order
// ...
}
The entire Javascript file only has a function sorta()
, which you have seen in the above demo. A quick reminder on the parameters:
instance
The HTML table itself.data
Optional, object data.
So the first thing we do is to initialize the sort mechanics by adding flags to the table. Yes, beginners, we can add variables to HTML elements in modern Javascript.
sBy
Sort by which column.sDirection
Sort in ascending (true
) or descending (false
) order.sOrder
The calculated sort order.
PART 2) SORT FUNCTION
// (B) ATTACH SORT FUNCTION TO TABLE
instance.sort = selected => {
// (B1) UPDATE SORT FLAGS
if (instance.sBy == selected.innerHTML) {
instance.sDirection = !instance.sDirection;
} else {
instance.sBy = selected.innerHTML;
instance.sDirection = true;
}
// (B2) UPDATE CSS OF HEADER CELLS
for (let c of instance.head.rows[0].cells) {
c.classList.remove("sortup");
c.classList.remove("sortdown");
if (c == selected) {
c.classList.add((instance.sDirection ? "sortup" : "sortdown"));
}
}
// (B3) MAP OUT DATA OF THE SELECTED COLUMN
// I.E. WE NEED TO RETAIN THE INDEX POSITIONS WHILE SORTING
let map = data[selected.innerHTML].map((v, i) => { return { i: i, v: v }; });
// (B4) SORT ARRAY
if (instance.sDirection) {
map.sort((a, b) => {
if (a.v > b.v) { return 1; }
if (a.v < b.v) { return -1; }
return 0;
});
} else {
map.sort((a, b) => {
if (a.v < b.v) { return 1; }
if (a.v > b.v) { return -1; }
return 0;
});
}
// (B5) REDRAW TABLE WITH NEW SORT ORDER
instance.sOrder = [];
for (let idx in map) { instance.sOrder.push(map[idx].i); }
delete(map); instance.draw();
};
Yikes, the next piece of confusion is called “sort”. Not going to explain this line-by-line, but the essentials are:
- As above. Keep in mind that the table
data
is kept in the format of{ HEAD : [ITEM, ITEM, ITEM] }
. - We will not mess with
data
directly, but calculate the sort order for[ITEM, ITEM, ITEM]
separately insOrder
. - When the user clicks on a header cell to sort:
- (B1) We set the “sort by this column”
sBy
and sort directionsDirection
. - (B3) Create a temporary
var map
with both the index and value of the items –var map = [{i:INDEX, v:ITEM}, {i:INDEX, v:ITEM}]
. - (B4) Sort the
map
. - (B5) Loop through
map
, extract only the index intosOrder
.
- (B1) We set the “sort by this column”
PART 3) DRAW TABLE ROWS
// (C) FUNCTION TO REDRAW TABLE DATA
instance.draw = () => {
// (C1) REMOVE OLD SORT ORDER
instance.body.innerHTML = "";
// (C2) DRAW NEW SORT ORDER
let r, c;
for (let i of instance.sOrder) {
r = instance.body.insertRow();
for (let key in data) {
c = r.insertCell();
c.innerHTML = data[key][i];
}
}
};
Once we have the sort order, we simply loop through sOrder
and draw the table rows.
PART 4) READ EXISTING TABLE
// (D) ADAPT EXISTING TABLE TO SORTABLE TABLE
if (data==undefined) {
// (D1) GET TABLE SECTIONS
instance.head = instance.querySelector("thead");
instance.body = instance.querySelector("tbody");
// (D2) GET DATA FROM HEADER
data = {}; keys = [];
for (let c of instance.head.rows[0].cells) {
data[c.innerHTML] = [];
keys.push(c.innerHTML);
}
// (D3) GET DATA FROM BODY
for (let r of instance.body.rows) { for (let i=0; i<r.cells.length; i++) {
data[keys[i]].push(r.cells[i].innerHTML);
}}
delete(keys);
}
Remember the data
parameter? For existing tables, we simply run through the table and adapt the data
.
PART 5) BUILD SORTABLE TABLE FROM OBJECT
// (E) DRAW SORTABLE TABLE FROM OBJECT
else {
// (E1) CREATE TABLE SECTIONS
instance.head = instance.createTHead();
instance.body = instance.createTBody();
// (E2) HEADER CELLS
let r = instance.head.insertRow();
r = instance.head.rows[0];
for (let key in data) {
let c = r.insertCell();
c.innerHTML = key;
}
// (E3) DEFAULT SORT ORDER & DRAW BODY
for (let i=0; i<data[Object.keys(data)[0]].length; i++) { instance.sOrder.push(i); }
instance.draw();
}
If an object data
is specified, we simply build the HTML from it.
PART 6) CSS CLASS & CLICK TO SORT
// (F) ADD CSS CLASS + ATTACH CLICK TO SORT
instance.classList.add("sorta");
for (let r of instance.head.rows) { for (let c of r.cells) {
c.onclick = () => instance.sort(c);
}}
This final part should be self-explanatory. We attach the “click to sort” on all header cells.
EXTRA BITS & LINKS
That’s all for this project, and here is a small section on some extras and links that may be useful to you.
LIMITATIONS & PERFORMANCE
This sortable table relies on ARRAY.sort()
– It should work pretty well and fast with most modern computers these days… But yep, it is not the most effective way to do sorting, and you will probably get hit with performance issues with large datasets.
NO “ERROR CHECKING”
Please make sure that your dataset and number of columns are correct on your own. I have contemplated adding an “auto check and fix”, but came to a simple conclusion:
- Checking massive datasets takes resources, it is simply not efficient to do so for the sake of “dummy proofing”.
- This is a “simple sortable table” tutorial, not “how to automatically fix your screw-up”.
- As a developer (or even as a user), you are responsible for the integrity of your own datasets.
- If there is a missing column or extra columns – Only you know what needs to be fixed.
COMPATIBILITY CHECKS
- Arrow Function – CanIUse
- Query Selector – CanIUse
All the required features are well-supported on modern browsers.
LINKS & REFERENCES
- Javascript Array Sort – MDN
- Javascript Array Reverse Sort – MDN
- Array Map – MDN
- Example on CodePen – Javascript Sortable Table
THE END
Thank you for reading, and we have come to the end of this guide. I hope that it has helped you with your project, and if you want to share anything with this guide, please feel free to comment below. Good luck and happy coding!
Hello, I am JS enthusiast but not a pro.
Well done but it crash when more column in bodythat in header (well ok that’s not supposed to be). Correction to allow more body column that header 🙂
Thanks for sharing. I will assume you mean “when the number of columns in the head and body doesn’t match”. I will add a check and throw errors in the future, but not “automatically fix it” by generating empty cells – Users should verify the data by themselves.
This is a very useful Javascript code. Thanks. I edited this code. Because sorting numbers is not really working on HTML table dom. Please check this: https://atakanau.blogspot.com/2020/12/sortable-table-using-pure-javascript.html