ali
ali

Reputation: 87

Turn html table data to run in a javascript loop

I have a table generated with Javascript that output some JSON data. Now I know I should probably not repeat myself so much but one of the element of this array needs to be wrapped in a link, and I don't know how to write a loop that output all members but the also member with some styling. Is there a way to do this in a loop, while keeping the format of output as this code gives? The table head part is already taken care of, the tbody is where I have problem: As you the last element didn't fit in a loop exactly. referring to this problem where I had it in a loop.

for (let j= 0; j< filtered.length; j++){
  var row = table.insertRow(1); 
  row.classList.add("headRow")
  var cell0 = row.insertCell(0);
  cell0.innerHTML = filtered[j].Carat;
  var cell1 = row.insertCell(1);
  cell1.innerHTML = filtered[j].Color;
  var cell2 = row.insertCell(2);
  cell2.innerHTML = filtered[j].Shape;
  var cell3 = row.insertCell(3);
  cell3.innerHTML = filtered[j].Cut;
  var cell4 = row.insertCell(4);
  cell4.innerHTML = filtered[j].Symmetry;
  var cell5 = row.insertCell(5);
  cell5.innerHTML = filtered[j].Report;
  var cell6 = row.insertCell(6);
  cell6.innerHTML = filtered[j].Clarity;
  var cell7 = row.insertCell(7);
  cell7.innerHTML = filtered[j].Polish;
  var cell8 = row.insertCell(8);
  cell8.innerHTML =  '<a href="' + filtered[j].link_view + '"> View</a>' ;
}

Upvotes: 2

Views: 603

Answers (2)

Romulo
Romulo

Reputation: 5104

You could try to create a configuration object containing the attribute that will be displayed at each row and a renderer function that will be used to determine how the data is going to be displayed.

Following is a quick example:

var renderer = {
    text: function(data) {
        return data;
    },
    link: function(data) {
        return '<a href="' + data + '">View</a>';
    }
};

var config = [
    {attr: "Carat", renderer: renderer.text},
    {attr: "Color", renderer: renderer.text},
    {attr: "Shape", renderer: renderer.text},
    {attr: "Cut", renderer: renderer.text},
    {attr: "Symmetry", renderer: renderer.text},
    {attr: "Report", renderer: renderer.text},
    {attr: "Clarity", renderer: renderer.text},
    {attr: "Polish", renderer: renderer.text},
    {attr: "link_view", renderer: renderer.link}
];

filtered.forEach(function(data) {

    var row = document.createElement("tr");

    config.forEach(function(entry) {

        var cell = document.createElement("td"),
            value = data[entry.attr];

        cell.innerHTML = entry.renderer(value);

        row.appendChild(cell);

    });

    table.appendChild(row);

});

Upvotes: 3

CertainPerformance
CertainPerformance

Reputation: 370679

Use an array of Carat, Color property names as strings, and loop over them to extract them from the object and create cells:

const props = ['Carat', 'Color', 'Shape']; // ...
for (let j= 0; j< filtered.length; j++){
  var row = table.insertRow(1);
  row.classList.add("headRow");
  props.forEach((prop) => {
    const cell = row.insertCell();
    cell.innerHTML = filtered[i][prop];
  });
  var cell8 = row.insertCell();
  cell8.innerHTML =  '<a href="' + filtered[j].link_view + '"> View</a>' ;
}

Note that unless the object values are composed of HTML markup, you should use textContent rather than innerHTML. (textContent is both faster and safer)

You don't have to specify an index when calling insertCell because you're inserting the cells in order:

index is the cell index of the new cell. If index is -1 or equal to the number of cells, the cell is appended as the last cell in the row. If index is greater than the number of cells, an IndexSizeError exception will result. If index is omitted it defaults to -1.

If filtered is an array, you can remove the need for ugly manual iteration by using forEach instead, if you wish:

const props = ['Carat', 'Color', 'Shape']; // ...
filtered.forEach((obj) => {
  var row = table.insertRow(1);
  row.classList.add("headRow");
  props.forEach((prop) => {
    const cell = row.insertCell();
    cell.innerHTML = obj[prop];
  });
  var cell8 = row.insertCell();
  cell8.innerHTML =  '<a href="' + obj.link_view + '"> View</a>' ;
});

Upvotes: 2

Related Questions