1
\$\begingroup\$

I'm displaying JSON data in a tabular format on a html page using jQuery.

In the function I'm looping the resp.DATA once to get the key names so it can be displayed as the headings in the table, and a second time to get the values of the keys for all customers.

Can this be done in a way that I only have to loop the resp.DATA once?

JSON data:

    var resp= {
    "ERROR": [],
    "DATA": [{
        "CustomerID": "234",
        "BranchID": "1",
        "LocationID": "26",
        "FirstName": "Lakshmi "
    }, {
        "CustomerID": "235",
        "BranchID": "1",
        "LocationID": "6",
        "FirstName": "Arora "
    }, {
        "CustomerID": "236",
        "BranchID": "1",
        "LocationID": "68",
        "FirstName": "S.K.Raman "
    }, {
        "CustomerID": "237",
        "BranchID": "1",
        "LocationID": "38",
        "FirstName": "Vidya Rao "
    }, {
        "CustomerID": "238",
        "BranchID": "1",
        "LocationID": "18",
        "FirstName": "Raju "
    }, {
        "CustomerID": "239",
        "BranchID": "1",
        "LocationID": "49",
        "FirstName": "K.B.Hebbar "
    }],
    "META": {
        "currentPageNumber": "1",
        "totalPages": "11",
        "rowcountCurrentPage": "10",
        "rowcountTotal": "107"
    }
}

Code:

            var content = '<table class="table table-hover">';
            var heading = "<tr>";
            var data = "";
            $.each(resp.DATA[0], function(ke, va) {
                heading += '<th>' + ke + '</th>';
            });
            $.each(resp.DATA, function(key, value) { 

                data += "<tr>";
                $.each(value, function(k, v) {
                   data += '<td>' + v + '</td>';
                });
                data += "</tr>";
            });
            heading += "</tr>";
           content += heading + data + "</table>";
            $('#data').append(content);

HTML file:

<!DOCTYPE html>
<html>
<head>
    <title>COnsuming rest webservice</title>
    <link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css"> </head>
<body>
    <h1>Consuming REST api</h1>
    <div class="container">
        <div id="data"> </div>
    </div>
    <!-- <input type="button" id="driver" value="Load Data" /> -->
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
    <script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
    </script>
</body>
</html>

You can see a working example here.

\$\endgroup\$
1
\$\begingroup\$

You may take advantage of reduce() and map() functions to have no loop at all, like this:

$('#data').append(
  resp.DATA.reduce((table, obj, index) => (
    table + (
      !index ? (
        Object.keys(obj).reduce((header, key) => `${header}<th>${key}`, '<tr>')
      ) : ''
    ) + $.map(obj, v => v).reduce((row, value) => `${row}<td>${value}`, '<tr>')
  ), '<table class="table table-hover">') + '</table>'
);

I also used some tagged strings, so more reducing the size of the code.
Additionally it works a bit faster than the original version, as you can observe with the following snippet.

var resp= {
  "ERROR": [],
  "DATA": [{
    "CustomerID": "234",
    "BranchID": "1",
    "LocationID": "26",
    "FirstName": "Lakshmi "
  }, {
    "CustomerID": "235",
    "BranchID": "1",
    "LocationID": "6",
    "FirstName": "Arora "
  }, {
    "CustomerID": "236",
    "BranchID": "1",
    "LocationID": "68",
    "FirstName": "S.K.Raman "
  }, {
    "CustomerID": "237",
    "BranchID": "1",
    "LocationID": "38",
    "FirstName": "Vidya Rao "
  }, {
    "CustomerID": "238",
    "BranchID": "1",
    "LocationID": "18",
    "FirstName": "Raju "
  }, {
    "CustomerID": "239",
    "BranchID": "1",
    "LocationID": "49",
    "FirstName": "K.B.Hebbar "
  }],
  "META": {
    "currentPageNumber": "1",
    "totalPages": "11",
    "rowcountCurrentPage": "10",
    "rowcountTotal": "107"
  }
}

var begTime = performance.now();var content = '<table class="table table-hover">';
var heading = "<tr>";
var data = "";
$.each(resp.DATA[0], function(ke, va) {
  heading += '<th>' + ke + '</th>';
});
$.each(resp.DATA, function(key, value) { 
  data += "<tr>";
  $.each(value, function(k, v) {
    data += '<td>' + v + '</td>';
  });
  data += "</tr>";
});
heading += "</tr>";
content += heading + data + "</table>";
$('#data').append(content);
$('#data').append(`<h3>OLD: ${performance.now() - begTime} ms</h3>`);

var begTime = performance.now();
$('#data').append(
  resp.DATA.reduce((table, obj, index) => (
    table + (
      !index ? (
        Object.keys(obj).reduce((header, key) => `${header}<th>${key}`, '<tr>')
      ) : ''
    ) + $.map(obj, v => v).reduce((row, value) => `${row}<td>${value}`, '<tr>')
  ), '<table class="table table-hover">') + '</table>'
);

$('#data').append(`<h3>NEW: ${performance.now() - begTime} ms</h3>`);
<!DOCTYPE html>
<html>
<head>
    <title>COnsuming rest webservice</title>
    <link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css"> </head>
<body>
    <h1>Consuming REST api</h1>
    <div class="container">
        <div id="data"> </div>
    </div>
    <!-- <input type="button" id="driver" value="Load Data" /> -->
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
    <script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
    </script>
</body>
</html>

NOTE: in your version as well as mine, we never take care of the keys in nested objects: they work only if they appear always in the same order!

|improve this answer|||||
\$\endgroup\$
0
\$\begingroup\$

try this one.i didn't test but hope it will work. You can replace search method to contains or indexof whatever..

var heading = "<tr>";
$.each(resp.DATA, function(key, value) { 

             data += "<tr>";
             $.each(value, function(k, v) {

           if(heading.search( k ) == -1)//allow key not found in existing value
                   heading += '<th>' + k + '</th>';

                   data += '<td>' + v + '</td>';
             });
             data += "</tr>";
 });

Finally append your strings

heading += "</tr>";
content += heading + data + "</table>";
$('#data').append(content);

2)
var headingArr=[];
    $.each(resp.DATA, function(key, value) { 

                 data += "<tr>";
                 $.each(value, function(k, v) {


                       heading.push('<th>' + k + '</th>');

                       data += '<td>' + v + '</td>';
                 });
                 data += "</tr>";
     });

remove duplicates using unique from headingArr array and convert array to string.after append it to ur html element.
|improve this answer|||||
\$\endgroup\$
  • \$\begingroup\$ code is working fine but in this code also the ` if(heading.search( k ) == -1)` will be executed many times i,e even when we get all the headings it will check No. of headings* No of k . This will be time consuming as the data iam applying this code is huge.. Thanks for ur response any help will be thankful. \$\endgroup\$ – Sandeep Feb 3 '16 at 11:01
  • \$\begingroup\$ @Sandeep plz check my another answer. \$\endgroup\$ – Itachi Uchiha Feb 3 '16 at 11:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.