Reputation: 2876
I have a JSON file and I am trying to return multiple HTML tables depending on the values of some columns in the JSON.
At the moment I have the following working. More specifically, it loads the JSON values into a table without any filters applying.
var data = {"headers":["plat","chan","group","03","cat","05","06","07","08","09","10","11","12","13","14","15","16","17"],"rows":[["plat1","chan1","aaaa","xxxxx","cat1","yyyy",133,236,0,"656",0,956,37,36,12,67,1],
["plat1","chan1","aaaa","xxxxx","cat2","yyyy",178,867,0,"656",0,647,39,12,18,65,2],
["plat1","chan1","bbb","xxxxx","cat1","yyyy",378,867,0,"656",0,350,32,97,19,64,3],
["plat1","chan1","bbb","xxxxx","cat2","yyyy",137,167,0,"656",0,523,46,86,32,62,4],
["plat2","chan1","aaaa","xxxxx","cat1","yyyy",133,236,0,"656",0,956,37,36,12,67,1],
["plat2","chan1","aaaa","xxxxx","cat2","yyyy",178,867,0,"656",0,647,39,12,18,65,2],
["plat2","chan1","bbb","xxxxx","cat1","yyyy",378,867,0,"656",0,350,32,97,19,64,3],
["plat3","chan1","bbb","xxxxx","cat2","yyyy",137,167,0,"656",0,523,46,86,32,62,4]]};
string = JSON.stringify(data);
//AAA Table + cat1
var table1 = '<div class="row"><div class="col-lg-6" style="background-color: #e90649; width: 117px;"> </div><div class="col-lg-6" style="max-width: 100px; padding-left: 10px; font-size: 2vw;">AAAA<br/><br/><span style="font-size: 1vw;">Cat1</span><br/><span style="font-size: 0.8vw; color: #ccc; font-weight: normal;">07 Jul 2017 - 18 Jul 2017</span></div><div class="col-lg-6"><div class="container"><table><thead><tr><th>plat</th><th>chan</th><th>03</th><th>05</th><th>06</th><th>07</th><th>08</th></tr></thead><tbody>';
$.each(data.rows, function(i) {
table1 +="<tr><td>" + data.rows[i][0] + "</td><td>" + data.rows[i][1] + "</td><td>" + data.rows[i][6] + "</td><td>" + data.rows[i][7] + "</td><td>" + data.rows[i][8] + "</td><td>" + data.rows[i][10] + "</td><td>" + data.rows[i][9] + "</td></tr>";
});
table1 += '</tbody></table></div></div></div>';
$("#one").html(table1);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div id="one"></div>
Combining the values of three columns, I have three different categories. For each category, JS will return an HTML table but with summed rows. For example, we have 2 rows for a combo of plat1 && chan1 && bbb but in the filtered table, I want to see 1 row with the numbers of the columns summed. As a start, I am trying to filter the JSON and create one table and I am stuck (I will update the question with any problems related to the summing of the numbers etc).
var data = {"headers":["plat","chan","group","03","cat","05","06","07","08","09","10","11","12","13","14","15","16","17"],"rows":[["plat1","chan1","aaaa","xxxxx","cat1","yyyy",133,236,0,"656",0,956,37,36,12,67,1],
["plat1","chan1","aaaa","xxxxx","cat2","yyyy",178,867,0,"656",0,647,39,12,18,65,2],
["plat1","chan1","bbb","xxxxx","cat1","yyyy",378,867,0,"656",0,350,32,97,19,64,3],
["plat1","chan1","bbb","xxxxx","cat2","yyyy",137,167,0,"656",0,523,46,86,32,62,4],
["plat2","chan1","aaaa","xxxxx","cat1","yyyy",133,236,0,"656",0,956,37,36,12,67,1],
["plat2","chan1","aaaa","xxxxx","cat2","yyyy",178,867,0,"656",0,647,39,12,18,65,2],
["plat2","chan1","bbb","xxxxx","cat1","yyyy",378,867,0,"656",0,350,32,97,19,64,3],
["plat3","chan1","bbb","xxxxx","cat2","yyyy",137,167,0,"656",0,523,46,86,32,62,4]]};
string = JSON.stringify(data);
var table1 = '';
$.each(data.rows, function(i) {
//JSON to string for the Regex check
if(JSON.stringify(data.rows[i][0]).match(/plat1/) && JSON.stringify(data.rows[i][4]).match(/cat1/) && JSON.stringify(data.rows[i][2]).match(/bbb/))
{
table1 += '<div class="row"><div class="col-lg-6" style="background-color: #e90649; width: 117px;"> </div><div class="col-lg-6" style="max-width: 100px; padding-left: 10px; font-size: 2vw;">BBB<br/><br/><span style="font-size: 1vw;">Cat1</span><br/><span style="font-size: 0.8vw; color: #ccc; font-weight: normal;">07 Jul 2017 - 18 Jul 2017</span></div><div class="col-lg-6"><div class="container"><table><thead><tr><th>plat</th><th>chan</th><th>03</th><th>05</th><th>06</th><th>07</th><th>08</th></tr></thead><tbody>';
$.each(data.rows, function(i)
{
table1 +="<tr><td>" + data.rows[i][0] + "</td><td>" + data.rows[i][1] + "</td><td>" + data.rows[i][6] + "</td><td>" + data.rows[i][7] + "</td><td>" + data.rows[i][8] + "</td><td>" + data.rows[i][10] + "</td><td>" + data.rows[i][9] + "</td></tr>";
});
table1 += '</tbody></table></div></div></div>';
};
});
$("#one").html(table1);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div id="one"></div>
I am trying to think of the best way doing that. I will definitely need a loop in order to check a) How many different combinations I have, b) To create the table in the HTML, c) To create the subtable that shows the JSON data.
Upvotes: 1
Views: 238
Reputation: 5010
Like I said in the comments I think a nicer approach is to transform the raw data to a more usable format, and then have separate logic to display the tables. Here I have an example of how to transform the data so that each row knows about the association between the header name and the data.
When the data is in the right format, it becomes easier to see how you would, for example, sum the values in one column (sum values associated with a specific header name). I've included an example of that as well.
You can also see how I divide a big problem like printing a table, in smaller steps (getting the table header, getting ONE table row). Then I combine these smaller functions to get the wanted behavior.
For data transformation it's very useful to get to know the Array methods, like .map
, .forEach
and .reduce
. I have examples of each of them. Mozilla have good documentation of these methods (see above).
I hope this helps you see how you could continue breaking down the problem until you have all the functionality you wanted. Feel free to ask me if you have further questions!
EDIT: The integrated code here in SO is bit hard to work with, so I have a JSFiddle demo you could see here: https://jsfiddle.net/jonahe/jLnph69s/
EDIT 2: New JSFiddle demo Now with a printed example of sums:
https://jsfiddle.net/jonahe/ntmg68dp/ As you can see, it relies heavily on reusing the smaller functions from before.
var data = {"headers":["plat","chan","group","03","cat","05","06","07","08","09","10","11","12","13","14","15","16","17"],"rows":[["plat1","chan1","aaaa","xxxxx","cat1","yyyy",133,236,0,"656",0,956,37,36,12,67,1],
["plat1","chan1","aaaa","xxxxx","cat2","yyyy",178,867,0,"656",0,647,39,12,18,65,2],
["plat1","chan1","bbb","xxxxx","cat1","yyyy",378,867,0,"656",0,350,32,97,19,64,3],
["plat1","chan1","bbb","xxxxx","cat2","yyyy",137,167,0,"656",0,523,46,86,32,62,4],
["plat2","chan1","aaaa","xxxxx","cat1","yyyy",133,236,0,"656",0,956,37,36,12,67,1],
["plat2","chan1","aaaa","xxxxx","cat2","yyyy",178,867,0,"656",0,647,39,12,18,65,2],
["plat2","chan1","bbb","xxxxx","cat1","yyyy",378,867,0,"656",0,350,32,97,19,64,3],
["plat3","chan1","bbb","xxxxx","cat2","yyyy",137,167,0,"656",0,523,46,86,32,62,4]]};
// transform the data to get a clear connection between the
// heading and the corresponding data
const transformedData = data.rows.map((row) => {
const emptyRowDataObject = {};
return row.reduce((dataObjSoFar, rowData, rowDataIndex) => {
// for each of the values in the row, add a property
// with the name of the corresponding header
const correspondingHeader = data.headers[rowDataIndex];
dataObjSoFar[correspondingHeader] = rowData;
return dataObjSoFar;
}, emptyRowDataObject);
});
const headersOfInterest = ['plat', 'chan', '03', '05', '06', '07', '08'];
printTable(headersOfInterest, transformedData);
console.log('sum of column 06 is: ' , getSumOfValuesInColumn('06', transformedData));
console.log('transformed data looks like', transformedData);
function printTable(headers, rowDataWithHeaders) {
let tableHeader = createTableHeaders(headers);
let tableRows = rowDataWithHeaders.map(row => createTableRow(headers, row));
let table = `<table>${ tableHeader }<tbody>${ tableRows }</tbody></table>`;
$("#one").html(table);
}
function createTableHeaders(headers) {
let headersHTML = '<thead><tr>';
headers.forEach(header => {
headersHTML += `<th>${ header }</th>`;
});
headersHTML += '</tr></thead>';
return headersHTML;
}
function createTableRow(headers, dataRow) {
let tr = '<tr>';
// go through all the headers we are interested in
// and get the corresponding value from this data row
headers.forEach(header => {
tr += `<td>${ dataRow[header] }</td>`;
});
tr += '</tr>';
return tr;
}
function getSumOfValuesInColumn(headerName, rowDataWithHeaders) {
// this could be done with Array.reduce as well
let sum = 0;
for(let i = 0; i < rowDataWithHeaders.length; i++) {
sum += rowDataWithHeaders[i][headerName]
}
return sum;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="one"></div>
Upvotes: 1