Getting data from JSON and formatting this into a table - javascript

I am getting a little stuck with this one. I am trying to use javascript on my website to convert my API JSON data to a table. Without using an array in an array of data in JSON, it works fine which each item on a new line but soon as I use an nested array of data in there, it has all the data on one line, seperated by a comma. Thinking a for loop would work here but i'm not 100% sure if this is the best method.
I have tried multiple searches online and tested around myself but I can't seem to get it to work.
The following is simple version of the JSON data I am working with:
MACLIST = ["ABC","DEF"]
IPLIST = ["10.10.10.10","20.20.20.20"]
ZONELIST = ["Inside","Outside"]
var json = [{"MAC":MACLIST,"IP":IPLIST,"ZONE":ZONELIST},{"SOMETHING ELSE":"OK"}];
Script used:
$(document).ready(function () {
ko.applyBindings({
teams: json
});
});
HTML used:
<table>
<thead>
<tr>
<th>Device</th>
<th>IP</th>
<th>Zone</th>
</tr>
</thead>
<tbody data-bind="foreach: teams">
<tr>
<td data-bind="text: MAC"></td>
<td data-bind="text: IP"></td>
<td data-bind="text: ZONE"></td>
</tr>
</tbody>
</table>
Working JSON version (without nested array data) works:
var json = [{"MAC":"ABC","IP":"10.10.10.10","ZONE":"Inside"},{"MAC":"DEF","IP":"20.20.20.20","ZONE":"Outside}];
Any tips or advice would be greatly appreciated
Testing URL JSFiddle Link

You can map over each row to create a string of html for each row. Then inside each row, map over each column to create the string of html for each cell.
var json = [{
"MAC": "ABC",
"IP": "10.10.10.10",
"ZONE": "Inside"
}, {
"MAC": "DEF",
"IP": "20.20.20.20",
"ZONE": "Outside"
}];
const makeCell = (content) => {
return `<td>${content}</td>`
}
const makeRow = (content) => {
return `<tr>${content}</tr>`
}
const table = document.querySelector('.table')
const colHeaders = Object.keys(json[0]).map(key => makeCell(key)).join('')
const bodyRows = json.map(row => {
return makeRow(Object.keys(row).map(col => makeCell(row[col])).join(''))
}).join('')
document.querySelector('thead tr').innerHTML = colHeaders
document.querySelector('tbody').innerHTML = bodyRows
<table>
<thead>
<tr></tr>
</thead>
<tbody>
</tbody>
</table>

Hopefully this article will help you resolve the problem
https://www.geeksforgeeks.org/how-to-convert-json-data-to-a-html-table-using-javascript-jquery/

Related

Dynamic JSON object to Html Table

I have gone through this solution Parsing JSON objects for HTML table . But in this solution Object keys are pre-defined when creating table. But I have some json data which can have random data.
Somtimes it can be :
var data = {
"C#": 2172738,
"CSS": 9390,
"HTML": 135085,
"Java": 337323
}
Or, Sometimes it can be:
var data = {
"Go": 2172738,
"Ruby": 9390,
"Dart": 135085
}
That means keys are not fixed. That data object can be dynamic. I want to convert the dynamic object to html table. Let's say, I have a table where thead is defined and tbody is empty:
<table id="_myTable">
<thead>
<th>Language</th>
<th>Line of Codes</th>
</thead>
<tbody>
</tbody>
</table>
How should I approach to insert that dynamic object data to tbody.
You can use for...in, Template literals and element.insertAdjacentHTML(position, text); to accomplish your task:
var data = {
"C#": 2172738,
"CSS": 9390,
"HTML": 135085,
"Java": 337323
}
for (key in data) {
var tr = `<tr><td>${key}</td><td>${data[key]}</td></tr>`;
document.querySelector('#_myTable tbody').insertAdjacentHTML('beforeend', tr);
}
<table id="_myTable">
<thead>
<th>Language</th>
<th>Line of Codes</th>
</thead>
<tbody>
</tbody>
</table>
You can use Object.keys(data) to get all of keys for "language" table data and Object.values(data) or Object.keys(data).map(key => data[key]) for "line of codes" table data.

NodeJS: How can I scrape two different tables, that are visually part of the same table, into one JSON Object?

Here's an example of the table of data I'm scraping:
The elements in red are in the <th> tags while the elements in green are in a <td> tag, the <tr> tag can be displayed according to how they're grouped (i.e. '1' is in it's own <tr>; HTML snippet:
EDIT: I forgot to add the surrounding div
<div class="table-cont">
<table class="tg-1">
<thead>
<tr>
<th class="tg-phtq">ID</td>
</tr>
</thead>
<tbody>
<tr>
<td class="tg-0pky">1</td>
<td class="tg-0pky">2</td>
<td class="tg-0pky">3</td>
</tr>
</tbody>
</table>
<table class="tg-2">
<thead>
<tr>
<th class="tg-phtq">Sample1</td>
<th class="tg-phtq">Sample2</td>
<...the rest of the table code matches the pattern...>
</tr>
</thead>
<tbody>
<tr>
<td class="tg-0pky">Swimm</td>
<td class="tg-dvpl">1:30</td>
<...>
</tr>
</tbody>
<...the rest of the table code...>
</table>
</div>
As you can see, in the HTML they're actually two different tables while they're displayed in the above example as only one. I want to generate a JSON object where the keys and values include the data from the two tables as if they were one, and output a single JSON Object.
How I'm scraping it right now is a bit of modified javascript code I found on a tutorial:
EDIT: In the below, I've been trying to find a way to select all relevant <th> tags from both tables and insert them into the same array as the rest of the <th> tag array and do the same for <tr> in the table body; I'm fairly sure for the th I can just insert the element separately before the rest but only because there's a single one - I've been having problems figuring out how to do that for both arrays and make sure all the items in the two arrays map correctly to each other
EDIT 2: Possible solution? I tried using XPath Selectors and I can use them in devTools to select everything I want, but page.evaluate doesn't accept them and page.$x('XPath') returns JSHandle#node since I'm trying to make an array, but I don't know where to go from there
let scrapeMemberTable = async (page) => {
await page.evaluate(() => {
let ths = Array.from(document.querySelectorAll('div.table-cont > table.tg-2 > thead > tr > th'));
let trs = Array.from(document.querySelectorAll('div.table-cont > table.tg-2 > tbody > tr'));
// the above two lines of code are the main problem area- I haven't been
//able to select all the head/body elements I want in just those two lines of code
// just removig the table id "tg-2" seems to deselect the whole thing
const headers = ths.map(th => th.textContent);
let results = [];
trs.forEach(tr => {
let r = {};
let tds = Array.from(tr.querySelectorAll('td')).map(td => td.textContent);
headers.forEach((k,i) => r[k] = tds[i]);
results.push(r);
});
return results; //results is OBJ in JSON format
}
}
...
results = results.concat( //merge into one array OBJ
await scrapeMemberTable(page)
);
...
Intended Result:
[
{
"ID": "1", <-- this is the goal
"Sample1": "Swimm",
"Sample2": "1:30",
"Sample3": "2:05",
"Sample4": "1:15",
"Sample5": "1:41"
}
]
Actual Result:
[
{
"Sample1": "Swimm",
"Sample2": "1:30",
"Sample3": "2:05",
"Sample4": "1:15",
"Sample5": "1:41"
}
]

HTML to JS Object

I am using handlebars to compile and get the html from the JS object. Is it possible to transform (html) back to JS object (using handlebars or anyother library)? To be more precise; Using handlebars, I have the following template:
<tr>
<td>{{qty}}</td>
<td>{{rate}}</td>
<td>{{gstPerc}}</td>
<td>{{discountPerc}}</td>
<td>{{amount}}</td>
</tr>
and following JS Object:
{
qty : 12,
rate : 1000,
gstPerc : 10,
discountPerc : 2,
amount: 1500
}
after compilation using handlebars, it gets transform to simple html i.e following, for example.
<tr>
<td>12</td>
<td>1000</td>
<td>10</td>
<td>2</td>
<td>1500</td>
</tr>
Now what I was wondering is, Is it possible (using handlebars), to transform the given HTML back to the object?
give give data-name as qty ,rate etc
var obj = getElementsByTagName('td');
$data = {};
for(var i=0;i<obj.length;i++)
{
$data[obj[i].dataset.name] = obj[i].innerHtml;
}
you can do reverse process you want to populate table with object data
You can use grid control like jqgrid for easy integration
For arbitrary templates and values, this is not possible. Consider the following template:
<td>{{cell1}}</td><td>{{cell2}}</td>
and the following result:
<td></td><td></td><td></td>
Which of cell1, cell2 is empty, and which contains </td><td>?
If you know the HTML inserted is valid and you know the template in advance, this is easy. For your specific template:
var table = document.createElement("table")
table.innerHTML = input
var tds = table.rows[0].cells
return {qty: tds[0].innerHTML, rate: tds[1].innerHTML ...}
If you know the values inserted should be numbers, you can convert them as such:
return {qty: +tds[0].innerHTML, rate: +tds[1].innerHTML ...}
Maybe you could use jQuery and end up with something like this
In your template: add classes to the <td> elements:
<table>
<tr id='someId'>
<td class='qty'>12</td>
<td class='rate'>1000</td>
<td class='gstPerc'>10</td>
<td class='discountPerc'>2</td>
<td class='amount'>1500</td>
</tr>
</table>
Create your object again:
var myObj = {};
$("#someId td").each(function() {
var td = $(this);
myObj[td.attr("class")] = td.text();
});
alert(JSON.stringify(myObj));

how to convert/transform an HTML table tbody (with rowspans) TO json?

I have an HTML table with combined row td's, or how to say, I don't know how to express myself (I am not so good at English), so I show it! This is my table:
<table border="1">
<thead>
<tr>
<th>line</th>
<th>value1</th>
<th>value2</th>
</tr>
</thead>
<tbody>
<tr>
<td rowspan="2">1</td>
<td>1.1</td>
<td>1.2</td>
</tr>
<tr>
<td>1.3</td>
<td>1.4</td>
</tr>
<tr>
<td rowspan="2">2</td>
<td>2.1</td>
<td>2.2</td>
</tr>
<tr>
<td>2.3</td>
<td>2.4</td>
</tr>
</tbody>
</table>
(you can check it here)
I want to convert this table to a JSON variable by jquery or javascript.
How should it look like, and how should I do it? Thank you, if you can help me!
if you want to convert only text use this one :
var array = [];
$('table').find('thead tr').each(function(){
$(this).children('th').each(function(){
array.push($(this).text());
})
}).end().find('tbody tr').each(function(){
$(this).children('td').each(function(){
array.push($(this).text());
})
})
var json = JSON.stringify(array);
To make a somehow representation of your table made no problem to me, but the problem is how to parse it back to HTML! Here a JSON with the first 6 tags:
{"table":{"border":1,"thead":{"th":{"textContent":"line","tr":"textContent":"value1",...}}}}}...
OR for better understanding:
{"tag":"table","border":1,"child":{"tag":"thead","child":{"tag":"th","textContent":"line",
"child":{"tag":"tr","textContent":"value1","child":...}}}}...
Closing tags are included.
For further explanations I need to know whether your table is a string or part of the DOM.
I belive this is what you want:
var jsonTable = {};
// add a new array property named: "columns"
$('table').find('thead tr').each(function() {
jsonTable.columns = $(this).find('th').text();
};
// now add a new array property which contains your rows: "rows"
$('table').find('tbody tr').each(function() {
var row = {};
// add data by colum names derived from "tbody"
for(var i = 0; i < jsonTable.columnsl.length; i++) {
row[ col ] = $(this).find('td').eq( i ).text();
}
// push it all to the results..
jsonTable.rows.push( row );
};
alert(JSON.stringify(jsonTable));
I think there should be some corrections, but this is it I think.

How do I get Mustache to render this data

I am new to the mustache template library and have the following scenario. I am retrieving both a template and the data from a web server. I am trying to combine the two using the following code:
function formatSearchResults(results)
{
dojo.xhrGet({
url:"search_result_template.mch",
handleAs:"text",
load: function(template)
{
//Load the template into a hidden div on the page
var templateNode = dojo.byId("templateArea")
templateNode.innerHTML = template;
}
});
var templateNode = dojo.byId("templateArea");
var formattedResults;
formattedResults = Mustache.to_html(templateNode.innerHTML,results);
var templateNode = dojo.byId("outputArea");
outputArea.innerHTML = formattedResults;
}
Retrieving the json and the template work fine. But the mustache never renders my data.
I have this json data:
{
"data": [
{
"ColumnValues": {
"_0": "Bubbles",
"_1": "Thompson%20Trucking",
"_2": "A633937432DF91212431251256D350",
"_3": "Eagleton",
"_4": "CA",
"_5": "555-555-5555",
"_6": "12121",
"_7": "Midatlantic",
"_8": "Thompson%20Trucking..<snip>,
"_9": ""
}
}, <snip>
]
}
and this mustache template:
<table id="orgInfo">
<tr>
<th>Search results: <br/><br/></th>
</tr>
<tr>
<td>Organization</td>
<td>City</td>
<td>State</td>
<td>Phone</td>
<td>Region</td>
<td>Industry</td>
<td>Description</td>
</tr>
{{data}}
{{#ColumnValues}}
<tr>
<td>{{_0}}</td>
<td></td>
<td></td>
<td></td>
<td>Region</td>
<td>Industry</td>
<td></td>
</tr>
{{/ColumnValues}}
{{/data}}
and this is the output I get:
{{/data}}
Search results:
Organization City State Phone NAICS Region Industry Description
NAICS Region Industry`
I have been over the docs and examples for hours. Can anybody tell me what I am doing wrong?
Thanks!
Kelvin
I think you need to change
{{data}}
into
{{#data}}
Ok. I now feel like a dope. I was not converting the json text to an object before passing it to the mustache library. All is well now. I hope this helps someone else who makes the same goofy mistake.

Categories