Create HTM table from JSON - javascript

I am trying to create a table from a JSON:
[
{
"title": "example",
"daymatch": [
{
"id": 1,
"date": "18. Februar 2023",
"name": "sample",
"accessories": [
{
"id": 1,
"accessoriesname": "device",
"price": "20.0"
},
{
"id": 2,
"accessoriesname": "deviceTwo",
"price": "10.0"
},
{
"id": 3,
"accessoriesname": "deviceThree",
"price": "56.80"
}
]
}
]
}
]
In the HTML I have created a template
<template id="example-template">
<div class="col-xs-12 col-sm-6">
<table class="table text-center">
<thead>
<tr>
<th colspan="2" class="id">Evaluation</th>
</tr>
</thead>
<tbody>
<tr id="accessorie">
<td class="accessoriesname">accessoriesname</td>
<td class="price">price</td>
</tr>
</tbody>
</table>
</div>
</template>
<main>
<div id="example-div"></div>
The JavaScript file
fetch("example.json")
.then((response) => {
return response.json();
})
.then((users) => {
const container = document.getElementById("example-div");
let userList = users[0].daymatch;
for (let i = 0; i < userList.length; i++) {
const elList = userList[i];
const tmpl = document
.getElementById("example-template")
.content.cloneNode(true);
tmpl.querySelector(".id").innerText = elList.name;
let userListName = userList[i].accessories;
var headd = "";
var bodyy = "";
for (let x = 0; x < userListName.length; x++) {
const elName = userListName[x];
const myList = document.createElement("tr");
console.log(elName.accessoriesname);
}
container.appendChild(tmpl);
}
});
The values from accessories should appear as single lines in the table. But I can't get to them via the tag template.
How do I get the individual "accessories" into the respective lines?
I get the values via the for loop, but how do I get the eizelen tr

The template’s content in the HTML is a DocumentFragment with three child nodes -- the div between two #text nodes. This code picks out the div element, adds it to the “example-div” element and then calls querySelector on the added element to find its tbody and tr elements. It saves the tr element to be used as a template, and then empties the tbody. Then it steps through the accessories array, cloning the saved tr element template for each item, and adding the cloned row to the tbody. It finds each of the row's td elements by its class name and sets its value.
fetch("example.json")
.then((response) => {
return response.json();
})
.then((users) => {
const tmpl = document.getElementById("example-template");
const container = document.getElementById("example-div");
const tmplClone = tmpl.content.cloneNode(true);
const template = container.appendChild(tmplClone.childNodes.item(1));
const rowTemplate = template.querySelector('tr#accessorie');
const tbody = template.querySelector('table tbody');
for (let j = tbody.childNodes.length - 1; j >= 0; --j) {
tbody.childNodes.item(j).remove();
}
let daymatches = users[0].daymatch;
for (let i = 0; i < daymatches.length; i++) {
const daymatch = daymatches[i];
template.querySelector(".id").innerText = daymatch.name;
let accessories = daymatch.accessories;
for (let x = 0; x < accessories.length; x++) {
const accessory = accessories[x];
const rowClone = rowTemplate.cloneNode(true);
const row = tbody.appendChild(rowClone);
row.querySelector('.accessoriesname').innerText = accessory.accessoriesname;
row.querySelector('.price').innerText = accessory.price;
}
}
});

Related

Convert Json into table or structured data [duplicate]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking us to recommend or find a tool, library or favorite off-site resource are off-topic for Stack Overflow as they tend to attract opinionated answers and spam. Instead, describe the problem and what has been done so far to solve it.
Closed 8 years ago.
Improve this question
Is there any jQuery or javascript library that generates a dynamic table given json data?
I don't want to define the columns, the library should read the keys in the json hash and generate columns.
Of course, I can myself iterate through the json data and generate the html table. I just want to know if any such library exists which I can simply reuse.
Thanks all for your replies. I wrote one myself. Please note that this uses jQuery.
Code snippet:
var myList = [
{ "name": "abc", "age": 50 },
{ "age": "25", "hobby": "swimming" },
{ "name": "xyz", "hobby": "programming" }
];
// Builds the HTML Table out of myList.
function buildHtmlTable(selector) {
var columns = addAllColumnHeaders(myList, selector);
for (var i = 0; i < myList.length; i++) {
var row$ = $('<tr/>');
for (var colIndex = 0; colIndex < columns.length; colIndex++) {
var cellValue = myList[i][columns[colIndex]];
if (cellValue == null) cellValue = "";
row$.append($('<td/>').html(cellValue));
}
$(selector).append(row$);
}
}
// Adds a header row to the table and returns the set of columns.
// Need to do union of keys from all records as some records may not contain
// all records.
function addAllColumnHeaders(myList, selector) {
var columnSet = [];
var headerTr$ = $('<tr/>');
for (var i = 0; i < myList.length; i++) {
var rowHash = myList[i];
for (var key in rowHash) {
if ($.inArray(key, columnSet) == -1) {
columnSet.push(key);
headerTr$.append($('<th/>').html(key));
}
}
}
$(selector).append(headerTr$);
return columnSet;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<body onLoad="buildHtmlTable('#excelDataTable')">
<table id="excelDataTable" border="1">
</table>
</body>
I have rewritten your code in vanilla-js, using DOM methods to prevent html injection.
Demo
var _table_ = document.createElement('table'),
_tr_ = document.createElement('tr'),
_th_ = document.createElement('th'),
_td_ = document.createElement('td');
// Builds the HTML Table out of myList json data from Ivy restful service.
function buildHtmlTable(arr) {
var table = _table_.cloneNode(false),
columns = addAllColumnHeaders(arr, table);
for (var i = 0, maxi = arr.length; i < maxi; ++i) {
var tr = _tr_.cloneNode(false);
for (var j = 0, maxj = columns.length; j < maxj; ++j) {
var td = _td_.cloneNode(false);
var cellValue = arr[i][columns[j]];
td.appendChild(document.createTextNode(arr[i][columns[j]] || ''));
tr.appendChild(td);
}
table.appendChild(tr);
}
return table;
}
// Adds a header row to the table and returns the set of columns.
// Need to do union of keys from all records as some records may not contain
// all records
function addAllColumnHeaders(arr, table) {
var columnSet = [],
tr = _tr_.cloneNode(false);
for (var i = 0, l = arr.length; i < l; i++) {
for (var key in arr[i]) {
if (arr[i].hasOwnProperty(key) && columnSet.indexOf(key) === -1) {
columnSet.push(key);
var th = _th_.cloneNode(false);
th.appendChild(document.createTextNode(key));
tr.appendChild(th);
}
}
}
table.appendChild(tr);
return columnSet;
}
document.body.appendChild(buildHtmlTable([{
"name": "abc",
"age": 50
},
{
"age": "25",
"hobby": "swimming"
},
{
"name": "xyz",
"hobby": "programming"
}
]));
You can use simple jQuery jPut plugin
http://plugins.jquery.com/jput/
<script>
$(document).ready(function(){
var json = [{"name": "name1","email":"email1#domain.com"},{"name": "name2","link":"email2#domain.com"}];
//while running this code the template will be appended in your div with json data
$("#tbody").jPut({
jsonData:json,
//ajax_url:"youfile.json", if you want to call from a json file
name:"tbody_template",
});
});
</script>
<table jput="t_template">
<tbody jput="tbody_template">
<tr>
<td>{{name}}</td>
<td>{{email}}</td>
</tr>
</tbody>
</table>
<table>
<tbody id="tbody">
</tbody>
</table>
Check out JSON2HTML http://json2html.com/ plugin for jQuery. It allows you to specify a transform that would convert your JSON object to HTML template. Use builder on http://json2html.com/ to get json transform object for any desired html template. In your case, it would be a table with row having following transform.
Example:
var transform = {"tag":"table", "children":[
{"tag":"tbody","children":[
{"tag":"tr","children":[
{"tag":"td","html":"${name}"},
{"tag":"td","html":"${age}"}
]}
]}
]};
var data = [
{'name':'Bob','age':40},
{'name':'Frank','age':15},
{'name':'Bill','age':65},
{'name':'Robert','age':24}
];
$('#target_div').html(json2html.transform(data,transform));

Javascript: How to iterate through an array of values and create table rows

I am fetching data from a server, I would like to iterate through the values and display them into the first column of the table. Any help that can steer me in the right direction would be appreciated.
Javascript
fetch(_____,{
}).then(data => {
var mstone = data.MilName;
var table = document.getElementById("milestone-table");
var row = table.insertRow(table.rows.length);
// var cell1 = row.insertCell(0);
//var cell2 = row.insertCell(1);
//cell1.setAttribute("style", "text-align:center");
//cell2.setAttribute("style", "text-align:center");
//Iterating through data values and trying to display onto table
for(var i = 0; i < mstone.length; i++){
var cell = row.insertCell(0);
cell.setAttribute("style", "text-align:center");
cell.innerHTML = mstone[i];
}
}).catch(function(err){
console.log("Fetch Problem: " + err);
});
You can set up the table in HTML without any of rows added, loop through the response data and add a row and cell for each item.
const data = ['foo', 'bar', 'baz'] // Dummy response data
const tbody = document.querySelector('tbody');
data.forEach(item => {
const tr = tbody.insertRow();
tr.insertCell().innerText = item
})
<table>
<thead>
<tr>
<th>Column Heading</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
Try some thing like below. Have nested loops (1 for rows and 1 for columns)
fetch("https://swapi.dev/api/planets/")
.then((res) => res.json())
.then((resp) => {
const results = resp.results;
var table = document.getElementById("table");
for (let j = 0; j < 4; j++) {
var row = table.insertRow(j);
for (var i = 0; i < 4; i++) {
var cell = row.insertCell(0);
cell.setAttribute("style", "text-align:center; border: 1px solid blue;");
cell.innerHTML = Object.values(results[j])[i];
}
}
});
<table id="table" style="border: 1px solid grey"></table>

Get nested array items to append to new column in HTML Table

I'm trying to append items from a 2D array into a table, but everything is appearing in the one column on the left. How can I separate tableDataArr[1] to start loading into the next column across?
Javascript
let names = []; //populated dynamically
let language = []; //populated dynamically
let tableDataArr = [names, language];
function renderData() {
for (let i = 0; i < tableDataArr.length; i++) {
tableDataArr[i].forEach(j => {
let newRow = document.createElement("tr");
newRow.className = "row";
newRow.innerHTML = `<td class='cell'>${j}</td>`;
leftTable.appendChild(newRow);
});
}
}
HTML
<div class='left-tbl-wrap'>
<table class='table' id='left-table'>
<tr class='row'>
<th class='th'>Name</th>
<th class='th'>Language</th>
<th class='th'>Latest tag</th>
<th class='th'><span class='delete'></span></th>
</tr>
</table>
</div>
For each iteration add name and language to the same row, then insert that row into table.
I added some elements in names and languages array to demostrate
let names = ["name1", "name2", "name3"]; //populated dynamically
let language = ["language1", "language2", "language3"]; //populated dynamically
let tableDataArr = [names, language];
const leftTable = document.querySelector("#left-table");
function renderData() {
tableDataArr[0].forEach((j, i) => {
let newRow = document.createElement("tr");
newRow.className = "row";
newRow.innerHTML = `<td class='cell'>${j}</td><td class='cell'>${tableDataArr[1][i]}</td>`;
leftTable.appendChild(newRow);
});
}
renderData();
<div class='left-tbl-wrap'>
<table class='table' id='left-table'>
<tr class='row'>
<th class='th'>Name</th>
<th class='th'>Language</th>
<th class='th'>Latest tag</th>
<th class='th'><span class='delete'></span></th>
</tr>
</table>
</div>
It should be like that
function renderData() {
for (let i = 0; i < tableDataArr.length; i++) {
let newRow = document.createElement("tr");
tableDataArr[i].forEach(j=> {
newRow.className = "row";
newRow.innerHTML = `<td class='cell'>${j}</td>`;
leftTable.appendChild(newRow);
});
}
}
Because you may do not need to iterate table row in the second loop. If you do like that it will be add each row with only one table data.

`appendChild(htmlobject)` only append the last child form an array of data

I'm making a shopping cart and will load the products of inside the cart after a XMLHttpRequest. Because the complexity of the table rows I've extracted this inside my HTML code (in code below see: #sampleBody). This contains the default markup of the row.
When I've done the request, I take the sampleBody and will append them to the cartBody. This I'll do alter every loop in over data. The problem is that only the first element is visible (I'm looping backwards).
P.S.: In code below I've just add the code what happens after the request.
(function() {
'use strict';
var sampleBody, cartBody;
var data = [{
name: "product 1",
price: 15,
quantity: 2,
total: 30
}, {
name: "name of product 2",
price: 10,
quantity: 3,
total: 30
}]
function init() {
sampleBody = document.getElementById('sampleBody');
cartBody = document.getElementById('cartBody');
}
init();
var renderCart = function(data) {
var html = document.createDocumentFragment();
for (var i = data.length; i--;) {
sampleBody.querySelector('#name').innerText = data[i].name;
sampleBody.querySelector('#price').innerText = data[i].price;
sampleBody.querySelector('#quantity').value = data[i].quantity;
sampleBody.querySelector('#total').innerText = data[i].total;
html.appendChild(sampleBody);
}
while (cartBody.firstChild) {
cartBody.removeChild(cartBody.firstChild);
}
cartBody.appendChild(html);
};
renderCart(data);
})();
.hidden {
display: none;
}
table {
width: 100%;
}
td, th {
border: solid 1px black;
padding: 5px;
}
<table>
<thead>
<tr>
<th>Name</th>
<th>Price</th>
<th>Quantity</th>
<th>Total</th>
</tr>
</thead>
<tbody id="cartBody">
<tr>
<td colspan="4">Loading...</td>
</tr>
</tbody>
</table>
<table class="hidden">
<tr id="sampleBody">
<td id="name"></td>
<td>€<span id="price"></span></td>
<td>
<button>+</button>
<input type="text" id="quantity">
<button>-</button>
</td>
<td>€<span id="total"></span></td>
</tr>
<table>
You have to clone your sampleBody node in your foor loop statement:
for (var i = data.length; i--;) {
var node = sampleBody.cloneNode(true);
node.setAttribute('id', node.getAttribute('id')+i);
node.querySelectorAll('*[id]').forEach(elt =>
elt.setAttribute('id', elt.getAttribute('id')+i)
);
node.querySelector('#name'+i).innerText = data[i].name;
node.querySelector('#price'+i).innerText = data[i].price;
node.querySelector('#quantity'+i).value = data[i].quantity;
node.querySelector('#total'+i).innerText = data[i].total;
html.appendChild(node);
}
We can also remove the ids and replace them by a name attribute:
HTML:
<table class="hidden">
<tr name="sampleBody">
<td name="name"></td>
<td>€<span name="price"></span></td>
<td>
<button>+</button>
<input type="text" name="quantity">
<button>-</button>
</td>
<td>€<span name="total"></span></td>
</tr>
<table>
JS:
...
function init() {
sampleBody = document.querySelector('table.hidden > tr[name="sampleBody"]');
cartBody = document.getElementById('cartBody');
}
...
for (var i = data.length; i--;) {
var node = sampleBody.cloneNode(true);
node.querySelector('*[name="name"]').innerText = data[i].name;
node.querySelector('*[name="price"]').innerText = data[i].price;
node.querySelector('*[name="quantity"]').value = data[i].quantity;
node.querySelector('*[name="total"]').innerText = data[i].total;
html.appendChild(node);
}
The issue is that id attribute values should be unique in valid HTML. So you should not use id for what you are doing. You can use class for this instead, and then filter for the one you want to assign the text to, like this:
for (var i = data.length; i--;) {
sampleBody.querySelectorAll('.name')[i].innerText = data[i].name;
sampleBody.querySelectorAll('.price')[i].innerText = data[i].price;
sampleBody.querySelectorAll('.quantity')[i].value = data[i].quantity;
sampleBody.querySelectorAll('.total')[i].innerText = data[i].total;
html.appendChild(sampleBody);
}
It would in fact be more efficient to perform those 4 querySelectorAll once, before the loop:
var names = sampleBody.querySelectorAll('.name');
var prices = sampleBody.querySelectorAll('.price');
var quantities = sampleBody.querySelectorAll('.quantity');
var totals = sampleBody.querySelectorAll('.total');
for (var i = data.length; i--;) {
names[i].innerText = data[i].name;
prices[i].innerText = data[i].price;
quantities[i].value = data[i].quantity;
totals[i].innerText = data[i].total;
html.appendChild(sampleBody);
}

Convert json data to a html table [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking us to recommend or find a tool, library or favorite off-site resource are off-topic for Stack Overflow as they tend to attract opinionated answers and spam. Instead, describe the problem and what has been done so far to solve it.
Closed 8 years ago.
Improve this question
Is there any jQuery or javascript library that generates a dynamic table given json data?
I don't want to define the columns, the library should read the keys in the json hash and generate columns.
Of course, I can myself iterate through the json data and generate the html table. I just want to know if any such library exists which I can simply reuse.
Thanks all for your replies. I wrote one myself. Please note that this uses jQuery.
Code snippet:
var myList = [
{ "name": "abc", "age": 50 },
{ "age": "25", "hobby": "swimming" },
{ "name": "xyz", "hobby": "programming" }
];
// Builds the HTML Table out of myList.
function buildHtmlTable(selector) {
var columns = addAllColumnHeaders(myList, selector);
for (var i = 0; i < myList.length; i++) {
var row$ = $('<tr/>');
for (var colIndex = 0; colIndex < columns.length; colIndex++) {
var cellValue = myList[i][columns[colIndex]];
if (cellValue == null) cellValue = "";
row$.append($('<td/>').html(cellValue));
}
$(selector).append(row$);
}
}
// Adds a header row to the table and returns the set of columns.
// Need to do union of keys from all records as some records may not contain
// all records.
function addAllColumnHeaders(myList, selector) {
var columnSet = [];
var headerTr$ = $('<tr/>');
for (var i = 0; i < myList.length; i++) {
var rowHash = myList[i];
for (var key in rowHash) {
if ($.inArray(key, columnSet) == -1) {
columnSet.push(key);
headerTr$.append($('<th/>').html(key));
}
}
}
$(selector).append(headerTr$);
return columnSet;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<body onLoad="buildHtmlTable('#excelDataTable')">
<table id="excelDataTable" border="1">
</table>
</body>
I have rewritten your code in vanilla-js, using DOM methods to prevent html injection.
Demo
var _table_ = document.createElement('table'),
_tr_ = document.createElement('tr'),
_th_ = document.createElement('th'),
_td_ = document.createElement('td');
// Builds the HTML Table out of myList json data from Ivy restful service.
function buildHtmlTable(arr) {
var table = _table_.cloneNode(false),
columns = addAllColumnHeaders(arr, table);
for (var i = 0, maxi = arr.length; i < maxi; ++i) {
var tr = _tr_.cloneNode(false);
for (var j = 0, maxj = columns.length; j < maxj; ++j) {
var td = _td_.cloneNode(false);
var cellValue = arr[i][columns[j]];
td.appendChild(document.createTextNode(arr[i][columns[j]] || ''));
tr.appendChild(td);
}
table.appendChild(tr);
}
return table;
}
// Adds a header row to the table and returns the set of columns.
// Need to do union of keys from all records as some records may not contain
// all records
function addAllColumnHeaders(arr, table) {
var columnSet = [],
tr = _tr_.cloneNode(false);
for (var i = 0, l = arr.length; i < l; i++) {
for (var key in arr[i]) {
if (arr[i].hasOwnProperty(key) && columnSet.indexOf(key) === -1) {
columnSet.push(key);
var th = _th_.cloneNode(false);
th.appendChild(document.createTextNode(key));
tr.appendChild(th);
}
}
}
table.appendChild(tr);
return columnSet;
}
document.body.appendChild(buildHtmlTable([{
"name": "abc",
"age": 50
},
{
"age": "25",
"hobby": "swimming"
},
{
"name": "xyz",
"hobby": "programming"
}
]));
You can use simple jQuery jPut plugin
http://plugins.jquery.com/jput/
<script>
$(document).ready(function(){
var json = [{"name": "name1","email":"email1#domain.com"},{"name": "name2","link":"email2#domain.com"}];
//while running this code the template will be appended in your div with json data
$("#tbody").jPut({
jsonData:json,
//ajax_url:"youfile.json", if you want to call from a json file
name:"tbody_template",
});
});
</script>
<table jput="t_template">
<tbody jput="tbody_template">
<tr>
<td>{{name}}</td>
<td>{{email}}</td>
</tr>
</tbody>
</table>
<table>
<tbody id="tbody">
</tbody>
</table>
Check out JSON2HTML http://json2html.com/ plugin for jQuery. It allows you to specify a transform that would convert your JSON object to HTML template. Use builder on http://json2html.com/ to get json transform object for any desired html template. In your case, it would be a table with row having following transform.
Example:
var transform = {"tag":"table", "children":[
{"tag":"tbody","children":[
{"tag":"tr","children":[
{"tag":"td","html":"${name}"},
{"tag":"td","html":"${age}"}
]}
]}
]};
var data = [
{'name':'Bob','age':40},
{'name':'Frank','age':15},
{'name':'Bill','age':65},
{'name':'Robert','age':24}
];
$('#target_div').html(json2html.transform(data,transform));

Categories