Explanation
What you want is to fill a table (or another DOMElement) in HTML, with your JavaScript, which is executed dynamically once the page is loaded and your JSON object is received.
You want to loop through the object. The best way to do so would be with a for loop, and making sure our looping variable remains valid for the length of our object (all its attributes).
The best way to get the length of a JSON object is through myJSONObject.length: You select the keys of myJSONObject and return their count.
You can access the values stored in your JSON Object the following way, in your for loop (assuming the looping variable defined is named i): myJSONObject[i].theAttributeIWantToGet
Price formatting breakdown
Now, those prices need to have a proper format, don't they? So we'll check if any of the value attribute has less than 2 characters after the . within them. If they do, we add another decimal 0. We also add a $ before writing the formatted value. Here is a breakdown of how it works:
obj[i].value.toString().substring(startIndex, length)- We want to check the length after the
.sign, so our startIndex will be the position of this dot within our string. obj[i].value.toString().substring(obj[i].value.toString().indexOf('.'),length)- We now need to set the length. We want to find the length of all what's after the dot, so we'll take the length of the whole string just to be safe.
Final result:
obj[i].value.toString().substring(obj[i].value.toString().indexOf('.'), obj[i].value.toString().length) < 2- This will return true or false. If it's true: There's less than 2 digits after the dot !
We add the
ifstatement and the last zero:if (obj[i].value.toString().substring(obj[i].value.toString().indexOf('.'), obj[i].value.toString().length) < 2) obj[i].value += "0";
- We want to check the length after the
Also: Why I use innerHTML instead of appendChild().
Solution
JSFiddle
HTML
<table>
<tbody id="tbody"></tbody>
</table>
JSON
[{
"key": "apple",
"value": 1.90
}, {
"key": "berry",
"value": 1.7
}, {
"key": "banana",
"value": 1.5
}, {
"key": "cherry",
"value": 1.2
}]
JavaScript
Note: The JSON object will be named obj in this instance.
var tbody = document.getElementById('tbody');
for (var i = 0; i < obj.length; i++) {
var tr = "<tr>";
/* Verification to add the last decimal 0 */
if (obj[i].value.toString().substring(obj[i].value.toString().indexOf('.'), obj[i].value.toString().length) < 2)
obj[i].value += "0";
/* Must not forget the $ sign */
tr += "<td>" + obj[i].key + "</td>" + "<td>$" + obj[i].value.toString() + "</td></tr>";
/* We add the table row to the table body */
tbody.innerHTML += tr;
}
JSFiddle
Answer from Jeff Noel on Stack OverflowExplanation
What you want is to fill a table (or another DOMElement) in HTML, with your JavaScript, which is executed dynamically once the page is loaded and your JSON object is received.
You want to loop through the object. The best way to do so would be with a for loop, and making sure our looping variable remains valid for the length of our object (all its attributes).
The best way to get the length of a JSON object is through myJSONObject.length: You select the keys of myJSONObject and return their count.
You can access the values stored in your JSON Object the following way, in your for loop (assuming the looping variable defined is named i): myJSONObject[i].theAttributeIWantToGet
Price formatting breakdown
Now, those prices need to have a proper format, don't they? So we'll check if any of the value attribute has less than 2 characters after the . within them. If they do, we add another decimal 0. We also add a $ before writing the formatted value. Here is a breakdown of how it works:
obj[i].value.toString().substring(startIndex, length)- We want to check the length after the
.sign, so our startIndex will be the position of this dot within our string. obj[i].value.toString().substring(obj[i].value.toString().indexOf('.'),length)- We now need to set the length. We want to find the length of all what's after the dot, so we'll take the length of the whole string just to be safe.
Final result:
obj[i].value.toString().substring(obj[i].value.toString().indexOf('.'), obj[i].value.toString().length) < 2- This will return true or false. If it's true: There's less than 2 digits after the dot !
We add the
ifstatement and the last zero:if (obj[i].value.toString().substring(obj[i].value.toString().indexOf('.'), obj[i].value.toString().length) < 2) obj[i].value += "0";
- We want to check the length after the
Also: Why I use innerHTML instead of appendChild().
Solution
JSFiddle
HTML
<table>
<tbody id="tbody"></tbody>
</table>
JSON
[{
"key": "apple",
"value": 1.90
}, {
"key": "berry",
"value": 1.7
}, {
"key": "banana",
"value": 1.5
}, {
"key": "cherry",
"value": 1.2
}]
JavaScript
Note: The JSON object will be named obj in this instance.
var tbody = document.getElementById('tbody');
for (var i = 0; i < obj.length; i++) {
var tr = "<tr>";
/* Verification to add the last decimal 0 */
if (obj[i].value.toString().substring(obj[i].value.toString().indexOf('.'), obj[i].value.toString().length) < 2)
obj[i].value += "0";
/* Must not forget the $ sign */
tr += "<td>" + obj[i].key + "</td>" + "<td>$" + obj[i].value.toString() + "</td></tr>";
/* We add the table row to the table body */
tbody.innerHTML += tr;
}
JSFiddle
It can be simply done by a small & smart process:
<table cellpadding="2" cellspacing="2" border="0" bgcolor="#dfdfdf" width="40%" align="center">
<thead>
<tr>
<th>Name</th>
<th width="20%">Age</th>
<th width="12%">Status</th>
</tr>
</thead>
<tbody id="tableData"></tbody>
</table>
<script type="text/javascript">
var mainObj = [
{
name: "Kapil",
age: 21,
status: "Active"
},
{
name: "John",
age: 28,
status: "Inactive"
},
{
name: "Deos",
age: 18,
status: "Active"
}
];
var k = '<tbody>'
for(i = 0;i < mainObj.length; i++){
k+= '<tr>';
k+= '<td>' + mainObj[i].name + '</td>';
k+= '<td>' + mainObj[i].age + '</td>';
k+= '<td>' + mainObj[i].status + '</td>';
k+= '</tr>';
}
k+='</tbody>';
document.getElementById('tableData').innerHTML = k;
</script>
Videos
Two issues at first:
- Is that Name or Nome? Please fix your typo (I know Nome is French, so if it's not typo, I suggest you introduce an i18n solution).
- Also please mind your syntax errors (some have given suggested edits that you could consider).
After that, here's my approach for programmatically create tables based on input data:
function buildTable(labels, objects, container) {
var table = document.createElement('table');
var thead = document.createElement('thead');
var tbody = document.createElement('tbody');
var theadTr = document.createElement('tr');
for (var i = 0; i < labels.length; i++) {
var theadTh = document.createElement('th');
theadTh.innerHTML = labels[i];
theadTr.appendChild(theadTh);
}
thead.appendChild(theadTr);
table.appendChild(thead);
for (j = 0; j < objects.length; j++) {
var tbodyTr = document.createElement('tr');
for (k = 0; k < labels.length; k++) {
var tbodyTd = document.createElement('td');
tbodyTd.innerHTML = objects[j][labels[k].toLowerCase()];
tbodyTr.appendChild(tbodyTd);
}
tbody.appendChild(tbodyTr);
}
table.appendChild(tbody);
container.appendChild(table);
}
var labels1 = ['ID', 'Name'];
var objects1 = [
{"id": "1", 'name': "richard"},
{"id": "2", 'name': "santos"}
];
var labels2 = ['ID', 'NOME'];
var objects2 = [
{"id": "1", 'nome': "richard"},
{"id": "2", 'nome': "adriana"}
];
var labels3 = ['ID', 'NAME', 'PLATE'];
var objects3 = [
{"id": "1", 'name': "jetta", 'plate': "DFG-1222"},
{"id": "2", 'name': "fusion", 'plate': "DFF-3342"}
];
buildTable(labels1, objects1, document.getElementById('a'));
buildTable(labels2, objects2, document.getElementById('b'));
buildTable(labels3, objects3, document.getElementById('c'));
table {
border-collapse: collapse;
}
th, td {
border: 1px solid black;
}
<div id="a"><p>Table 1</p></div>
<div id="b"><p>Table 2</p></div>
<div id="c"><p>Table 3</p></div>
This is a working procedure from our project. It has three parameters:
htmlTable(selector, data_array [, column_names]);
column_names parameter is optional: if you omit it the function creates column names from first row (if it exists).
It creates HTML tags directly into the DOM, but it can be rewritten to generate HTML as a string if you need . See the working snippet below:
var labels = ['id','name'];
var object = [{"id":"1",'name': "richard"},{"id":"2",'name': "santos"}];
htmlTable("#res0",object, labels);
var labels = ['id','nome'];
var object = [{"id":"1",'nome': "richard"},{"id":"2",'nome': "adriana"}];
htmlTable("#res1",object, labels);
var labels = ['id','name', 'plate'];
var object = [{"id":"1",'name': "jetta",'plate': "DFG-1222"},
{"id":"2",'name': "fusion",'plate': "DFF-3342"}];
htmlTable("#res2",object, labels);
// Without labels array
var data3 = [{a:1,c:2},{a:3,c:3}];
htmlTable("#res3",data3);
function htmlTable(selector, data, columns) {
var sel = document.querySelector(selector);
if(!sel) {
throw new Error('Selected HTML element is not found');
};
if((!columns) || columns.length == 0) {
columns = Object.keys(data[0]);
}
var tbe = document.createElement('table');
var thead = document.createElement('thead');
tbe.appendChild(thead);
var tre = document.createElement('tr');
for(var i=0;i<columns.length;i++){
var the = document.createElement('th');
the.textContent = columns[i];
tre.appendChild(the);
}
thead.appendChild(tre);
var tbody = document.createElement('tbody');
tbe.appendChild(tbody);
for(var j=0;j<data.length;j++){
var tre = document.createElement('tr');
for(var i=0;i<columns.length;i++){
var the = document.createElement('td');
the.textContent = data[j][columns[i]];
tre.appendChild(the);
}
tbody.appendChild(tre);
};
emptyDOMChildren(sel);
sel.appendChild(tbe);
};
// Utility function to fast delete all children of element if it is not empty
// Can be replaced with simple but relatively "slower" container.innerHTML = "";
function emptyDOMChildren (container){
var len = container.childNodes.length;
while (len--) {
container.removeChild(container.lastChild);
};
};
<div id="res0"></div>
<div id="res1"></div>
<div id="res2"></div>
<div id="res3"></div>
» npm install object-to-table
Let's start with your version:
1) Unnecessary optimization.
var array_length = Object.keys(basic_data).length;
var array_obj_names = Object.keys(basic_data);
This gives you nothing in terms of performance. It would be optimized away by the browser.
2) Chain-calling
$(table_id).empty();
$(table_id).append('<thead>');
It is possible to do chain-calls like: $('#elem').doA().doB().doC()
3) Misunderstanding calls
$(table_id).find('thead:last').append('<th>Tag');
.append() does exactly that: appending after the last element.
4) NuStyleLoopz
for (var i = 0; i < array_length; i++) {
var attr_name = array_obj_names[i];
var tag = '<td>' + array_obj_names[i];
var data = '<td>' + basic_data[attr_name];
You could iterate over the keys directly via Object.keys() with
Array.prototype.forEach()
Array.prototype.map()
Array.protoype.reduce() / Array.prototype.reduceRight().
Here a slighty pimped version:
makeTag=function(openTag, closeTag){
return function(content){
return openTag+content+closeTag;
};
};
tHead=makeTag("<thead>","</thead>");
tBody=makeTag("<tbody>","</tbody>");
td=makeTag("<td>","</td>");
tr=makeTag("<tr>","</tr>");
function insertBasicTable(data,id){
$('#'+id).html(
tHead(
tr(
td("Tag")+
td("Data")
)
)+
tBody(
Object.keys(data).reduce(function(o,n){
return o+tr(
td(n)+""+
td(data[n]+"")
);
},"")
)
);
};
insertBasicTable({"key1":"value1","key2":"value2"},"mytable");
Here is the fiddle to play with.
To make HTML-generation less painfull and a bit more JS-stylish I define what is called a higher order function makeTag: simply a function returning a function. A call to var tHead=makeTag("<thead>","</thead>"); generates an anonymous function (a function without name), which returns every time it's called "<thead>"+ parameter +"</thead>". The same goes for the other tags. This allows me to do something like a DSL:
tHead(
tr(
td("Tag")+
td("Data")
)
)
That is not only handy, but cool B-)
Besides it is nearly as readable as html and not so noisy like the typical string concatenation and the risk of typos is really low.
You should cache $table and $tbody, instead of re-instantiating them every time you need them.