You can avoid the need to generate HTML in a string and then add it manually to the page by manipulating the HTMLTableElement directly via JavaScript.
- When you invoke
HTMLTableElement#insertRow()
you add a new HTMLTableRowElement
- Calling
HTMLTableRowElement#insertCell
adds a new HTMLCellElement
- You can set
textContent
or createTextNode
and appendChild
to set the content of the cells. The results are the same - both are options.
// sample data
var exceptionData = [
[1, "ERROR"],
[2, "WARNING"],
[3, "INFORMATION"],
[4, "ERROR"],
[5, "WARNING"],
[6, "INFORMATION"],
[7, "OTHER"],
[8, "OTHER"]
];
//how to put the data in the table
var table = document.getElementById("data"); //selected an existing table
fillTable(table, exceptionData);
function fillTable(table, data) {
for (var i = 0; i < data.length; i++) {
var rowData = data[i];
var tableRow = table.insertRow();
//setting textContent of the cell
var idCell = tableRow.insertCell();
var id = rowData[0];
idCell.textContent = id;
//appending a textNode child to the cell
var typeCell = tableRow.insertCell();
var type = document.createTextNode(rowData[1]);
typeCell.appendChild(type)
}
}
table, th, td {
border: 1px black solid;
border-collapse: collapse;
}
<div id="tableDiv">
<table id="data">
<tr><th>Exception ID</th><th>Type</th></tr>
</table>
</div>
This works if you already have a table. If you want to create a table in-memory, then you can also do that using Document#createElement
and then add it via appendChild
. I've added HTMLTableELement#createTHead
to showcase it but you don't have to do that. I can't find a way to add <th>
elements programmatically from the table API, so I'm using Document#createElement
to make them as well - the <thead>
is a nice addition but non-essential to how a table would be rendered.
// sample data
var tableConfig = ["Exception ID", "Type"];
var exceptionData = [
[1, "ERROR"],
[2, "WARNING"],
[3, "INFORMATION"],
[4, "ERROR"],
[5, "WARNING"],
[6, "INFORMATION"],
[7, "OTHER"],
[8, "OTHER"]
];
//how make the table and put the data in
var table = createTable(tableConfig);
fillTable(table, exceptionData);
document.getElementById("tableDiv").appendChild(table);
function createTable(config) {
var table = document.createElement("table");
var tHead = table.createTHead();
var headerRow = tHead.insertRow();
for(var i = 0; i < config.length; i++) {
var th = document.createElement("th");
th.textContent = config[i];
headerRow.appendChild(th);
}
return table;
}
function fillTable(table, data) {
for (var i = 0; i < data.length; i++) {
var rowData = data[i];
var tableRow = table.insertRow();
for(var j = 0; j < rowData.length; j++) {
tableRow.insertCell().textContent = rowData[j]; //create and set the content
}
}
}
table, th, td {
border: 1px black solid;
border-collapse: collapse;
}
<div id="tableDiv"></div>
Creating the table in-memory and then appending it has the advantage of minimising the browser reflow which will occur if you update the table a lot. In the first example the table would have triggered a reflow for adding a row, adding a cell, adding data to the cell and each could be potentially expensive. With a large dataset, it could lead to really bad performance. If you create the table outside the DOM and then attach it, this will trigger a single reflow which, even if expensive, is much better than many times that.
Finally, here is the second example re-written in ES6 mainly to avoid the plain for
loops in favour of for...of
loops.
// sample data
const tableConfig = ["Exception ID", "Type"];
const exceptionData = [
[1, "ERROR"],
[2, "WARNING"],
[3, "INFORMATION"],
[4, "ERROR"],
[5, "WARNING"],
[6, "INFORMATION"],
[7, "OTHER"],
[8, "OTHER"]
];
//how make the table and put the data in
const table = createTable(tableConfig);
fillTable(table, exceptionData);
document.getElementById("tableDiv").appendChild(table);
function createTable(config) {
const table = document.createElement("table");
const tHead = table.createTHead();
const headerRow = tHead.insertRow();
for(header of config) {
const th = document.createElement("th");
th.textContent = header;
headerRow.appendChild(th);
}
return table;
}
function fillTable(table, data) {
for (rowData of data) {
const tableRow = table.insertRow();
for(cellData of rowData) {
tableRow.insertCell().textContent = cellData; //create and set the content
}
}
}
table, th, td {
border: 1px black solid;
border-collapse: collapse;
}
<div id="tableDiv"></div>