1

I want to display data in table row while extracting values from map object using JavaScript while AJAX success.

Below is my response that I got from server side:

reportData: 
  Compute: [2233.36, 2097.09, 2241.42, 2135.11, 2489.97, 2548.01, 2500.82, 2502.82, 2618.89, 2861.08, 2809.17]
  Disks: [985.73, 966.29, 987.02, 959.48, 1012.96, 1010.27, 1018.69, 1013.26, 1015.25, 1075.85, 1090.98]
  Images: [0.56, 0.56, 0.57, 0.55, 0.57, 0.56, 0.57, 0.57, 0.57, 0.6, 0.6, 0.59, 0.29, 7.16]
  Snapshots: [15.75, 11.09, 1.7, 1.65, 7.84, 7.68, 0.26, 1.45, 9.9, 4.55, 7.36, 7.15, 3.5, 79.87]
  Total: [2233.36, 2097.09, 2241.42, 2135.11, 2489.97, 2548.01, 2500.82, 2502.82, 2618.89, 2861.08, 2809.17]
  Virtual Machine: [1231.32, 1119.14, 1252.13, 1173.43, 1468.61, 1529.5, 1481.3, 1487.53, 1593.17, 1780.08, 1710.24]

So, this reportData is basically a Map object having compute, disks etc as values and these values further contains an array of some data. So I want to display like this:

compute 2233.36 2097.09 2241.42 .....
disks 985.73 966.29 987.02 .....
images 0.56 0.56 0.57 ..... 
.... and so on

This is my below code, and through this I am not able to render my table body as I am expecting.

function getReportData(report_id, client_id){
        $.ajax({
            url: "/emerge/mvc/ajax/clientreportsearch/ReportCostData",
            data: {
                report_id: report_id,
                client_id: client_id
            },
            type: "POST",
            success: function (response) {
                var tbody = "", data = "", td1 = "", td2 = "";
                var mapEntry = "";
                if(response.reportData != null){
                    mapEntry = response.reportData;
                    Object.keys(mapEntry).forEach(function(value, key){
                        if(value != 'Total'){
                            td1 = td1+ "<td>"+key+"</td>";
                            data = data + "<tr>"+td1;
                            for(var i = 0; i < value.length; i++){
                                td2 = td2 + "<td>"+value[i]+"</td>";
                            }
                        }
                    });
                    tbody = tbody+data;
                    document.getElementById('thead').innerHTML = thead;
                    document.getElementById('reportdataDiv').style.display = "inline";
                }
            },
            error: function (error) {
                console.log(`Error ${error}`);
            }
        });
    }

So, is there better solution?

Thank you.

screenshot to display output screenshot of response from server

3 Answers 3

1

var reportData = { 
  Compute: [2233.36, 2097.09, 2241.42, 2135.11, 2489.97, 2548.01, 2500.82, 2502.82, 2618.89, 2861.08, 2809.17],
  Disks: [985.73, 966.29, 987.02, 959.48, 1012.96, 1010.27, 1018.69, 1013.26, 1015.25, 1075.85, 1090.98],
  Images: [0.56, 0.56, 0.57, 0.55, 0.57, 0.56, 0.57, 0.57, 0.57, 0.6, 0.6],
  Snapshots: [15.75, 11.09, 1.7, 1.65, 7.84, 7.68, 0.26, 1.45, 9.9, 4.55, 7.36],
  Total: [2233.36, 2097.09, 2241.42, 2135.11, 2489.97, 2548.01, 2500.82, 2502.82, 2618.89, 2861.08, 2809.17],
  VirtualMachine: [1231.32, 1119.14, 1252.13, 1173.43, 1468.61, 1529.5, 1481.3, 1487.53, 1593.17, 1780.08, 1710.24]
 }

 var tBody = document.getElementById("body");

Object.keys(reportData).forEach(function(key, idx) {
  if(key != 'Total') {
    var tr = document.createElement("tr");

    var td = document.createElement("td");
    var product = document.createTextNode(key);
    td.appendChild(product);
    tr.appendChild(td);

    for(var i = 0; i < reportData[key].length; i++) {
      var td = document.createElement("td");
      var cellText = document.createTextNode(reportData[key][i]);
      td.appendChild(cellText);
      tr.appendChild(td);
    }

    tBody.append(tr);
  }
});
td{
  border: 1px solid #ddd;
}
<table cellpadding="1" cellspacing="1">
  <thead id="header">
    <tr>
      <th></th>
      <th>1</th>
      <th>2</th>
      <th>3</th>
      <th>4</th>
      <th>5</th>
      <th>6</th>
      <th>7</th>
      <th>8</th>
      <th>9</th>
      <th>10</th>
      <th>11</th>
    </tr>
  </thead>
  <tbody id="body">
  
  </tbody>
</table>

You can refer to the following example.

Hope this help!

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

Comments

1

I use create utility method to create HTML element, set its HTML content and append it to the parent. Then you can prepare HTML table and append it to some container:

const data = {
    reportData: {
        Compute: [2233.36, 2097.09, 2241.42, 2135.11, 2489.97, 2548.01, 2500.82, 2502.82, 2618.89, 2861.08, 2809.17],
        Disks: [985.73, 966.29, 987.02, 959.48, 1012.96, 1010.27, 1018.69, 1013.26, 1015.25, 1075.85, 1090.98],
        Images: [0.56, 0.56, 0.57, 0.55, 0.57, 0.56, 0.57, 0.57, 0.57, 0.6, 0.6, 0.59, 0.29, 7.16],
        Snapshots: [15.75, 11.09, 1.7, 1.65, 7.84, 7.68, 0.26, 1.45, 9.9, 4.55, 7.36, 7.15, 3.5, 79.87],
        Total: [2233.36, 2097.09, 2241.42, 2135.11, 2489.97, 2548.01, 2500.82, 2502.82, 2618.89, 2861.08, 2809.17],
        "Virtual Machine": [1231.32, 1119.14, 1252.13, 1173.43, 1468.61, 1529.5, 1481.3, 1487.53, 1593.17, 1780.08, 1710.24]
    }
}

const create = (name, parent, content) => {
    const node = document.createElement(name);
    parent.appendChild(node);
    if(content) node.innerHTML = content;
    return node;
}

const table = create("table", document.getElementById("test"));
const tbody = create("tbody", table);
for(let key of Object.keys(data.reportData)) {
    if(key === "Total") continue;

    const tr = create("tr", tbody);
    create("td", tr, key);

    for(let v of data.reportData[key]) {
        create("td", tr, v);
    }
}
<div id="test"></div>

Comments

1

It may be an idea to use insertAdjacentHTML to create the rows. Something like:

const reportData = { 
  Compute: [2233.36, 2097.09, 2241.42, 2135.11, 2489.97, 2548.01, 2500.82, 2502.82, 2618.89, 2861.08, 2809.17],
  Disks: [985.73, 966.29, 987.02, 959.48, 1012.96, 1010.27, 1018.69, 1013.26, 1015.25, 1075.85, 1090.98],
  Images: [0.56, 0.56, 0.57, 0.55, 0.57, 0.56, 0.57, 0.57, 0.57, 0.6, 0.6, 0.59, 0.29, 7.16],
  Snapshots: [15.75, 11.09, 1.7, 1.65, 7.84, 7.68, 0.26, 1.45, 9.9, 4.55, 7.36, 7.15, 3.5, 79.87],
  Total: [2233.36, 2097.09, 2241.42, 2135.11, 2489.97, 2548.01, 2500.82, 2502.82, 2618.89, 2861.08, 2809.17],
  'Virtual Machine': [1231.32, 1119.14, 1252.13, 1173.43, 1468.61, 1529.5, 1481.3, 1487.53, 1593.17, 1780.08, 1710.24], };

// not all rows have an equal amount of values, so:
const nColumns = Math.max.call( null, ...Object.values(reportData).map( v => v.length ) );

// create the table
document.body.insertAdjacentHTML(`beforeend`, `
  <table>
    <head>
      <tr>
         <th>ID</th>
         <th>${[...Array(nColumns)].map((c, i) => `c${i+1}`).join(`</th><th>`)}</th>
      </tr>
    </head>
    <tbody>
    </tbody>
  </table>
`);

// retrieve the table for adding rows
const tableBody = document.querySelector(`table tbody`);

// loop through [reportData] to create the rows:
Object.entries(reportData).forEach( ([rowLabel, values]) => {
  // fill shorter data arrays:
  values = values.length < nColumns ? values.concat(...[...Array(nColumns - values.length)].map(_ => `n/a`)) : values;
  
  // insert a row using the row label and values
  tableBody.insertAdjacentHTML(`beforeend`, `<tr><td>${rowLabel}</td><td>${values.join(`</td><td>`)}</td></tr>`);
} );
table {
  font: 12px/15px normal verdana, arial;
}

th {
  text-align: right;
  color: white;
  background-color: black;
  max-width: 200px;
  padding: 2px 5px 2px;
}

td {
  border: 1px solid #c0c0c0;
  text-align: right;
  max-width: 200px;
  padding: 2px 5px 2px;
}

td:first-child {
  color: green;
  background-color: #c0c0c0;
}

7 Comments

tableBody.insertAdjacentHTML(beforeend, <tr><td>${rowId}</td><td>${values.join(</td><td>)}</td></tr>); } ); is not working as expected.
How to make that thing a string?
As you can see when running the snippet it should work. Maybe you forgot the backticks (`) before and after?
So, do I need to use backticks with it?
Surrounding text with ", ' or ` makes it a string. Backticks make it a template string/literal. So, yeah.
|

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.