0

I am trying to create table from my JSON data which looks like this:

It works for a specific JSON data:

var items = [
{"Name":"A","Type":2,"Result":"0"},
{"Name":"A","Type":1,"Result":"1"},
{"Name":"B","Type":2,"Result":"1"},
{"Name":"B","Type":1,"Result":"0"},
]

But, it doesn't create table correctly if the columns ("Type") is random

var items = [
{"Name":"A","Type":5,"Result":"1"}
{"Name":"A","Type":2,"Result":"0"},
{"Name":"A","Type":1,"Result":"1"},
{"Name":"B","Type":3,"Result":"1"},
{"Name":"B","Type":2,"Result":"1"},
{"Name":"B","Type":1,"Result":"0"},
]

Can someone tell me what's the issue with my code? I want to create table for dynamic JSON data which may not have cell values for all the columns. With this code, I don't see entry in column 5 for A as 1.

function get_prop(obj, prop) {
   return prop.split('.').reduce((o,k) => obj[k], obj);
}

function coll2tbl(json, row_header, col_header, cell) {
var table = {};
var row_headers = [];
var cols = {};

json.map(function(a) {
    var h = get_prop(a, row_header);
    if (h in table === false) {
        table[h] = {};
        row_headers.push(h);
    }
    var c = get_prop(a, col_header);
    cols[c] = null;
    table[h][c] = get_prop(a, cell);
});

var cells = [];
for (var row in table) {
    cells.push(Object.values(table[row]));
}
console.log('row_headers' + row_headers);
console.log('Object.keys(cols)' + Object.keys(cols));
console.log('cells' + cells);

var headerRow = '<th>' + capitalizeFirstLetter('TestName') + '</th>';
var colKeys = Object.keys(cols);
colKeys.map(function(col) {
 headerRow += '<th>' + capitalizeFirstLetter(col) + '</th>';
});

var bodyRows = '';
for (var i in cells) {
  bodyRows += '<tr>'; 
  bodyRows += '<td>' + row_headers[i] + '</td>';
  for (var j in cells[i]) {
    console.log('Processing row: ' + row_headers[i] + ' result: ' + cells[i][j] + ' i=' + i + ' j=' + j);
    bodyRows += '<td>';
    if (cells[i][j] === "1") {
      bodyRows +=  '<font color="green">' + cells[i][j] + '</font>';
    }
    else if (cells[i][j] === "0") {
      bodyRows +=  '<font color="red">' + cells[i][j] + '</font>';
    }
    else if (cells[i][j] === "-1") {
      bodyRows +=  '<font color="orange">' + cells[i][j] + '</font>';
    }
    else {
      bodyRows +=  "-";
    }
    bodyRows += '</td>';
  }
  bodyRows += '</tr>';
}

//return { row_headers, col_headers: Object.keys(cols), cells };
return ('<table> <thead><tr>' + headerRow + '</tr></thead><tbody>' + bodyRows + '</tbody></table>');
}

function capitalizeFirstLetter(string) {return 
    string.charAt(0).toUpperCase() + string.slice(1);
}

coll2tbl(items, 'Name', 'Type', 'Result');

My table should like like this:

Name 1 2 3 4 5 
A    1 1 - - 1 
B    1 1 1 - -

1 Answer 1

1

The answer https://stackoverflow.com/a/52199138/10320683 is of course correct, but if you need or want to stick to your specific code, you can put this below your json.map (which should by the way use forEach and not map, since you do not use the returned array anyways)

  for (var col in cols) {
    for (row in table) {
      if (!table[row].hasOwnProperty(col)) {
        table[row][col] = "-";
      }
    }
  }

The reason why your code did not work is that by iterating over the rows, you do not get all the possible type properties, which becomes clear if you inspect your table variable: { a: {1: "1", 2: "0", 5: "1"}, b: {...}} (this is missing the 3 type property), so by calling Object.values(table[row]) later on, you get the following array for your cells: ["1", "0", "1"], but you do have 4 columns, so the "Type 5" result (1) gets shifted one column to the left.

Also, you need to be careful because your code is relying on the sorting that Object.values() produces, which means that if you want to change the order of your columns, your code would not work.

Sign up to request clarification or add additional context in comments.

1 Comment

The solution is correct for the data that was provided. However, The solution did not cover all the edge cases. Your fix to add entries for empty cells makes the solution more robust for other sets of data (such as mine). Thanks.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.