Home > Software design >  How to iterate a map object using JavaScript and extracting values from it?
How to iterate a map object using JavaScript and extracting values from it?

Time:01-18

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

CodePudding user response:

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!

CodePudding user response:

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>

CodePudding user response:

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>
`);
const tableBody = document.querySelector(`table tbody`);

// loop through [reportData] to create the rows:
Object.entries(reportData).forEach( ([rowId, values]) => {
  // fill shorter data arrays:
  values = values.length < nColumns ? values.concat(...[...Array(nColumns - values.length)].map(_ => `n/a`)) : values;
  tableBody.insertAdjacentHTML(`beforeend`, `<tr><td>${rowId}</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;
}

  • Related