1. Putting Content material With HTML
The <desk>
tag is the semantic HTML tag used for displaying information on a webpage. We’ll be putting our <desk>
tag inside a table-container div which is able to enable us embody some responsive styling in CSS.
<div class="table-container"> <desk class="data-table"> </desk> </div>
Our desk will comprise the desk header, thead
and desk content material, tbody
tags. In our desk header, we’ll embody buttons in every th
cell which will probably be used to deal with the sorting performance. The cells for desk content material will added in with JavaScript utilizing the information from our JSON response.
<div class="table-container"> <desk class="data-table"> <thead> <tr> <th><button id="title">Title</button></th> <th><button id="sort">Sort</button></th> <th><button id="hp">HP</button></th> <th><button id="assault">Assault</button></th> <th><button id="protection">Protection</button></th> <th><button id="spAttack">Sp. Assault</button></th> <th><button id="spDefense">Sp. Protection</button></th> <th><button id="velocity">Velocity</button></th> <th><button id="complete">Whole</button></th> </tr> </thead> <tbody id="table-content"></tbody> </desk> </div>
2. Making a Responsive Desk with CSS
One of many extra widespread issues of working with HTML tables is an absence of responsiveness. The desk might need a cell overlap drawback or transcend the boundaries of the complete web page.
We are able to do away with these points by putting the desk in a table-container that’s the width of the complete web page with an overflow scroll property. That method, the desk is all the time solely as vast as the complete web page and there is no must shrink the cells because of the scrollable overflow. We’ll additionally embody min-width properties on our desk cells to keep away from textual content wrapping.
That is the CSS wanted to make our desk scrollable:
.table-container { width: 100%; overflow: scroll; } desk { width: 100%; }
We are able to then add the remainder of our styling:
.table-container { margin: auto; max-width: 1200px; min-height: 100vh; overflow: scroll; width: 100%; } desk { border-collapse: collapse; width: 100%; } thead tr { border-bottom: 1px stable #ddd; border-top: 1px stable #ddd; top: 1px; } th { font-weight: daring; top: inherit; padding: 0; } th:not(:first-of-type) { border-left: 1px stable #ddd; } th button { background-color: #eee; border: none; cursor: pointer; show: block; font: inherit; top: 100%; margin: 0; min-width: max-content; padding: 0.5rem 1rem; place: relative; text-align: left; width: 100%; } tbody tr { border-bottom: 1px stable #ddd; } td { padding: 0.5rem 1rem; text-align: left; }
3. Putting JSON Knowledge in an HTML Desk
For this instance, we’ll be working with a mock parsed JSON response. That is what our information seems like:
const response = { "pokedata": [ { "name": "Bulbasaur", "type": "Grass", "hp": 45, "attack": 49, "defense": 49, "spAttack": 65, "spDefense": 65, "speed": 45, "total": 318 }, ... ] }
We’ll be putting the information inside our <tbody id="table-content">
tag so we’ll goal that factor in JavaScript;
const tableContent = doc.getElementById("table-content")
The row content material will probably be based mostly on every object inside our response.pokedata
. Let’s outline a perform for creating a brand new row based mostly on the item information:
const createRow = (obj) => { const row = doc.createElement("tr"); const objKeys = Object.keys(obj); objKeys.map((key) => { const cell = doc.createElement("td"); cell.setAttribute("data-attr", key); cell.innerHTML = obj[key]; row.appendChild(cell); }); return row; };
On this perform, we use the Object.keys()
technique to get the item keys as an array. That is what the returned worth seems like:
As soon as we’ve gotten the array of the item keys, we loop by way of every key utilizing the .map()
technique. The map technique carries out the perform we’ve handed into it on every merchandise within the array.
On this map perform, we’re creating a brand new cell for every merchandise within the array and setting the cell innerHTML because the corresponding object key worth.
Lastly, we append the cell we’ve created to the row outlined originally of the perform utilizing the .appendChild()
technique.
Now that we now have our row creating perform, we’ll outline a perform to loop by way of the response.pokedata
array and append every new row to our tableContent
factor.
const getTableContent = (information) => { information.map((obj) => { const row = createRow(obj); tableContent.appendChild(row); }); };
We’ll go our getTableContent
perform into an occasion listener so the content material is added to the desk as soon as the web page masses.
window.addEventListener("load", () => { getTableContent(response.pokedata); });
4. Sorting Knowledge With JavaScript
Now that we now have created our desk, let’s add the sorting performance. In our HTML, we included buttons within the header cells which had the item keys as their id. Let’s goal these buttons now:
const tableButtons = doc.querySelectorAll("th button");
We need to deal with sorting the information in accordance with which button is clicked and likewise embody a function that toggles the sorting course (ascending or descending) when the button is clicked.
We are able to use the .type()
technique to deal with sorting the information in our response.pokedata
array. The type technique takes in a perform evaluating two completely different params and types them in accordance with the perform response:
compareFunction(a, b) return worth
|
type order |
---|---|
> 0 |
type a after b
|
< 0 | type a earlier than b |
=== 0 | hold authentic order of a and b
|
Supply: MDN
One other factor to notice concerning the type technique is that it mutates the unique array that it operates on. This implies it modifications the worth of our authentic array.
We are able to keep away from mutating our authentic array by utilizing the unfold syntax […]
Now we are able to create our sorting perform. That is what the logic for our sorting perform will seem like:
- Clear the content material within the tableContent factor
- Kind the information in accordance with the chosen param and course
- Append the sorted information to our tableContent utilizing the
getTableContent
perform
const sortData = (information, param, course = "asc") => { tableContent.innerHTML = ''; const sortedData = course == "asc" ? [...data].type(perform (a, b) { if (a[param] < b[param]) { return -1; } if (a[param] > b[param]) { return 1; } return 0; }) : [...data].type(perform (a, b) { if (b[param] < a[param]) { return -1; } if (b[param] > a[param]) { return 1; } return 0; }); getTableContent(sortedData); };
Our type perform takes three parameters:
-
information
: the array to be sorted -
param
: the worth getting used to type the array -
course
: type the array in both ascending or descending order. The default paramater worth is ready to “asc”.
We clear the content material in our tableContent factor by setting the innerHTML to a clean string. We then use the .type()
technique and course
parameter to find out how the information must be sorted. We reverse the examine perform as a way to type in descending order. Utilizing the examine perform this fashion lets us type the information whatever the sort worth (string, integer, float and so forth)
Lastly, we go the sortedData
as the brand new worth in our desk content material.
Now we’ll go our type perform right into a click on occasion listener for our desk buttons and likewise deal with toggling the kind course.
window.addEventListener("load", () => { getTableContent(response.pokedata); [...tableButtons].map((button) => { button.addEventListener("click on", (e) => { if (e.goal.getAttribute("data-dir") == "desc") { sortData(response.pokedata, e.goal.id, "desc"); e.goal.setAttribute("data-dir", "asc"); } else { sortData(response.pokedata, e.goal.id, "asc"); e.goal.setAttribute("data-dir", "desc"); } }); }); });
On this perform, we deal with the toggling by setting a data-dir
attribute on our buttons to find out the sorting course. We’ll additionally replace our CSS to show an icon subsequent to the button relying on the sorting course:
th button::after { place: absolute; proper: 0.5rem; } th button[data-dir="asc"]::after { content material: url("information:picture/svg+xml,%3Csvg xmlns="https://www.w3.org/2000/svg" width="8" top="8"%3Epercent3Cpolygon factors="0, 0 8,0 4,8 8" fill="%23818688"/%3Epercent3C/svgpercent3E"); } th button[data-dir="desc"]::after { content material: url("information:picture/svg+xml,%3Csvg xmlns="http://www.w3.org/2000/svg" width="8" top="8"%3Epercent3Cpolygon factors="4 0,8 8,0 8" fill="%23818688"/%3Epercent3C/svgpercent3E"); }
We don’t need to have the icons present up on all beforehand clicked buttons so we’ll outline a resetButtons
perform that removes the data-dir attribute on any button that’s not the button clicked.
const resetButtons = (occasion) => { [...tableButtons].map((button) => { if (button !== occasion.goal) { button.removeAttribute("data-dir"); } }); };
We’ll go that perform into our button occasion listener to reset the earlier buttons every time a brand new button is clicked
window.addEventListener("load", () => { getTableContent(response.pokedata); [...tableButtons].map((button) => { button.addEventListener("click on", (e) => { resetButtons(e); if (e.goal.getAttribute("data-dir") == "desc") { sortData(response.pokedata, e.goal.id, "desc"); e.goal.setAttribute("data-dir", "asc"); } else { sortData(response.pokedata, e.goal.id, "asc"); e.goal.setAttribute("data-dir", "desc"); } }); }); });
Conclusion
And with that, we’re finished! We’ve created a sortable desk utilizing solely vanilla JavaScript!