18

I am a beginner of JavaScript and want to display an array of objects in HTML.

The format of the data is like this:

[
  {"key":"apple","value":1.90},
  {"key":"berry","value":1.7},
  {"key":"banana","value":1.5},
  {"key":"cherry","value":1.2}
]

I want to use a list with three columns (id, name, relevance) to display them. And the id can increase from 1 automatically.

Could anyone tell me how to write a javascript code to display it?

Please give me some materials or examples to learn.

Brad
  • 159,648
  • 54
  • 349
  • 530
Bin Zhu
  • 201
  • 1
  • 2
  • 6
  • This might help: http://stackoverflow.com/questions/4935632/how-to-parse-json-in-javascript?rq=1 – DevlshOne Jul 16 '13 at 18:24
  • Do you just want to print it into an HTML table, is that the idea? – SimplGy Jul 16 '13 at 18:26
  • Can you provide the HTML code that you would like to have at the end? That would make it much easier to give you an accurate answer. – talemyn Jul 16 '13 at 18:26
  • I'd suggest reading an HTML DOM tutorial. – Dan455 Jul 16 '13 at 18:27
  • maybe something like parse the json (jquery) `$.parseJSON(json..)` and then run through each element of array and append proper values in proper places – Kamil Jul 16 '13 at 18:28
  • @Brad I deleted it, I assumed that was what he wanted since he didn't give any html – aaronman Jul 16 '13 at 18:28
  • If you're just interested in getting it to display, take a look at http://datatables.net/ – Mike Robinson Jul 16 '13 at 18:28
  • Correct me if i am wrong--->you want to parse this json and display it in your html??Is this what you want – HIRA THAKUR Jul 16 '13 at 18:28
  • @MESSIAH, you are right. I want to parse it and display it. I don't know how to parse it. And I am not sure which html structure is better to display it. Table or something else? – Bin Zhu Jul 16 '13 at 18:38
  • @talemyn, the page is just to use to display this data.So nothing else is in this page – Bin Zhu Jul 16 '13 at 18:39
  • @Simple As Could Be , yes, you are right. I think table is good, but I don't know if there is a better structure in html to display it? – Bin Zhu Jul 16 '13 at 18:41
  • Imho using a [table](http://jsfiddle.net/mjE7R/7/show) for tabular data is absolutely ok. – Stano Jul 16 '13 at 20:11

9 Answers9

20

Explanation

What you want is to fill a table (or another DOMElement) in HTML, with your JavaScript, which is executed dynamically once the page is loaded and your JSON object is received.

You want to loop through the object. The best way to do so would be with a for loop, and making sure our looping variable remains valid for the length of our object (all its attributes).

The best way to get the length of a JSON object is through myJSONObject.length: You select the keys of myJSONObject and return their count.

You can access the values stored in your JSON Object the following way, in your for loop (assuming the looping variable defined is named i): myJSONObject[i].theAttributeIWantToGet


Price formatting breakdown

Now, those prices need to have a proper format, don't they? So we'll check if any of the value attribute has less than 2 characters after the . within them. If they do, we add another decimal 0. We also add a $ before writing the formatted value. Here is a breakdown of how it works:

  • obj[i].value.toString().substring(startIndex, length)

    • We want to check the length after the . sign, so our startIndex will be the position of this dot within our string.
    • obj[i].value.toString().substring(obj[i].value.toString().indexOf('.'),length)
    • We now need to set the length. We want to find the length of all what's after the dot, so we'll take the length of the whole string just to be safe.
    • Final result: obj[i].value.toString().substring(obj[i].value.toString().indexOf('.'), obj[i].value.toString().length) < 2

      • This will return true or false. If it's true: There's less than 2 digits after the dot !
    • We add the if statement and the last zero:

    • if (obj[i].value.toString().substring(obj[i].value.toString().indexOf('.'), obj[i].value.toString().length) < 2) obj[i].value += "0";

Also: Why I use innerHTML instead of appendChild().


Solution

JSFiddle

HTML

<table>
    <tbody id="tbody"></tbody>
</table>

JSON

[{
    "key": "apple",
    "value": 1.90
}, {
    "key": "berry",
    "value": 1.7
}, {
    "key": "banana",
    "value": 1.5
}, {
    "key": "cherry",
    "value": 1.2
}]

JavaScript

Note: The JSON object will be named obj in this instance.

var tbody = document.getElementById('tbody');

for (var i = 0; i < obj.length; i++) {
    var tr = "<tr>";

    /* Verification to add the last decimal 0 */
    if (obj[i].value.toString().substring(obj[i].value.toString().indexOf('.'), obj[i].value.toString().length) < 2) 
        obj[i].value += "0";

    /* Must not forget the $ sign */
    tr += "<td>" + obj[i].key + "</td>" + "<td>$" + obj[i].value.toString() + "</td></tr>";

    /* We add the table row to the table body */
    tbody.innerHTML += tr;
}

JSFiddle

Asif Raza
  • 3,435
  • 2
  • 27
  • 43
Jeff Noel
  • 7,500
  • 4
  • 40
  • 66
  • 1
    "Object.keys(obj).length" <- this is quite ugly; it's better to use obj.length – Dima Jul 16 '13 at 18:40
  • @Dima: You are right. I thought I could optimize performance, [but that was a stupid mistake from my part](http://jsperf.com/object-keys-length-vs-object-length). I'll go get another coffee. – Jeff Noel Jul 16 '13 at 18:47
  • @Stano The question was not about CSS nor format. I used long variable names for the clarity and ease of understandability over minified, yet performant, code. I get what you mean though. – Jeff Noel Jul 16 '13 at 19:10
  • Yes that CSS is non essential, only meant that innerHTML can be moved outside the loop. But your answer is ok. – Stano Jul 16 '13 at 19:12
8

It can be simply done by a small & smart process:

<table cellpadding="2" cellspacing="2" border="0" bgcolor="#dfdfdf" width="40%" align="center">
<thead>
    <tr>
        <th>Name</th>
        <th width="20%">Age</th>
        <th width="12%">Status</th>
    </tr>
</thead>
    <tbody id="tableData"></tbody>
</table>
<script type="text/javascript">
    var mainObj = [
        {
            name: "Kapil",
            age:  21,
            status: "Active"
        },
        {
            name: "John",
            age:  28,
            status: "Inactive"
        },
        {
            name: "Deos",
            age:  18,
            status: "Active"
        }
    ];
    var k = '<tbody>'
    for(i = 0;i < mainObj.length; i++){
        k+= '<tr>';
        k+= '<td>' + mainObj[i].name + '</td>';
        k+= '<td>' + mainObj[i].age + '</td>';
        k+= '<td>' + mainObj[i].status + '</td>';
        k+= '</tr>';
    }
    k+='</tbody>';
    document.getElementById('tableData').innerHTML = k;
    </script>
afxentios
  • 2,502
  • 2
  • 21
  • 24
Kapil Chhabra
  • 415
  • 5
  • 7
6

You can do something like this:

var table = document.createElement("table");

//Add a header
var header = document.createElement("tr");

var idHeaderCell = document.createElement("th");
var nameHeaderCell = document.createElement("th");
var relevanceHeaderCell = document.createElement("th");

header.appendChild(idHeaderCell);
header.appendChild(nameHeaderCell);
header.appendChild(relevanceHeaderCell);

table.appendChild(header);

//Add the rest of the data to the table
for(var i = 0; i < data.length; i++) {
    var id = (i + 1);
    var name = data[i].key;
    var relevance = data[i].value;

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

    var idCell = document.createElement("td");
    var nameCell = document.createElement("td");
    var relevanceCell = document.createElement("td");

    idCell.appendChild(document.createTextNode(id));
    nameCell.appendChild(document.createTextNode(name));
    relevanceCell.appendChild(document.createTextNode(relevance));

    tr.appendChild(idCell);
    tr.appendChild(nameCell);
    tr.appendChild(relevanceCell);

    table.appendChild(tr);
}
Vivin Paliath
  • 94,126
  • 40
  • 223
  • 295
  • OP: In case of bigger JSON objects, I would suggest you to use `innerHTML` over `appendChild()`, [**performance-wise**](http://jsperf.com/html-innerhtml-vs-appendchild). – Jeff Noel Jul 16 '13 at 18:59
  • It works, only you forgot to create the tBody element: http://jsfiddle.net/mjE7R/6/ When using innerHTML or jQuery, the tBody tag is implicitly created: http://jsfiddle.net/mjE7R/3/ (you can inspect generated structure in Page Inspector). So here the tBody should be created manually (at least for a bit better compatibility with jQuery). – Stano Jul 16 '13 at 19:30
4

Here a function for build a table from any collection (array of objects)

Table creator

const data=[
    {
        name: "Kapil",
        age:  21,
        status: "Active"
    },
    {
        name: "John",
        age:  28,
        status: "Inactive"
    },
    {
        name: "Deos",
        age:  18,
        status: "Active",
        testing: 'Gooo!!'
    }
]

const createTable=function(data){
const table = document.createElement("table");
const header = document.createElement("tr");
const keys=Object.keys(data[0])
console.log(keys)
for(const key of keys){
    const th=document.createElement("th");
    th.appendChild(document.createTextNode(key));
    header.appendChild(th);
}
table.appendChild(header);
const len=data.length
for(const row of data) {
    const tr = document.createElement("tr");
    for(const key of keys){
        const td = document.createElement("td");
        const content=row[key] ||''
        td.appendChild(document.createTextNode(content));
        tr.appendChild(td);
        delete row[key]
    }
  /****
  you can omit next cycle if all object have the same structor or if the first element of collection have all fields
  ****/
    for(const key in  row){
        const th=document.createElement("th");
        th.appendChild(document.createTextNode(key))
        keys.push(key)
        header.appendChild(th);
        const td = document.createElement("td");
        const content=row[key] ||''
        td.appendChild(document.createTextNode(content));
        tr.appendChild(td);
    }
    table.appendChild(tr);
}
return table

}

cesarve
  • 274
  • 3
  • 9
3

Array.map() combined with template literals comes in really handy for rendering HTML markup within Javascript for large objects in a scalable manner:

function tableMarkupFromObjectArray(obj) {

  let headers = `
  <th>Index</th>
  ${Object.keys(obj[0]).map((col) =>`
  <th>${col}</th>`
  ).join('')}`

  let content = obj.map((row, idx) => `
<tr>
      <td>${idx}</td>
      ${Object.values(row).map((datum) => `
      <td>${datum}</td>`
    ).join('')}
    </tr>
`).join('')

  let tablemarkup = `
  <table>
    ${headers}
    ${content}
  </table>
  `
  return tablemarkup
}


let myobj =[
  { "name": "apple", "rel": 1.90 },
  { "name": "berry", "rel": 1.7 },
  { "name": "banana", "rel": 1.5 },
  { "name": "cherry", "rel": 1.2 }
]

document.querySelector("#mydiv").innerHTML = tableMarkupFromObjectArray(myobj)

http://jsfiddle.net/4L7c5vad/

msweeney
  • 31
  • 1
2

Here is my ES6 solution. I have used the reduce operation to construct a Set storing the keys from all objects in the array:

    function arrayToTable(data) {
        const keys = [...data.reduce((all, obj)=>{
            Object.keys(obj).forEach(key => all.add(key));
            return all;
        }, new Set())];

        const header = keys.map(key => `<th>${key}</th>`).join('')
        const tbody = data.map(row => keys.map(key => `<td>${row[key]}</td>`).join('')).map(row => `<tr>${row}</tr>`)

        return `<table>
            <thead><tr>${header}</tr></thead>
            <tbody>${tbody}</body>
        </table>`;
    }
noam gaash
  • 337
  • 2
  • 13
1

Iterate through the list and retrieve the data for each item this way (assuming your data is in a var called data):

for (var i = 0; i < data.length; i++) {
  var id = i + 1;
  var name = data[i].key;
  var relevance = data[i].value;
}

Then, do something with the variables in each loop, print them out however you want.

Lochemage
  • 3,974
  • 11
  • 11
  • I don't know how to generate some html code to display these data in this loop. Could you give me some code example? Thx a lot. :) – Bin Zhu Jul 16 '13 at 18:42
1

I am not totally sure what you are asking for. The title of you post seems like you are looking for JSON.stringfy like mentioned in the previous answer but apparently you are not.

Are you trying to create and HTML list, ? Can you please try to explain your need again? I doubt what you are trying to do is complicated and I sure we can help you if you give a little more detail and purpose of what you are trying to do.

I am going to guess that you are trying to display HMTL by looping over you JSON object. Try this pure JavaScript example:

var fruits = JSON.parse('[{"key":"apple","value":1.90}, {"key":"berry","value":1.7}, {"key":"banana","value":1.5}, {"key":"cherry","value":1.2} ]');

var tbl = document.createElement('table');
var thead = document.createElement("thead");
var tbody = document.createElement("tbody")

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

var th_id = document.createElement("th");
var th_name = document.createElement("th");
var th_price = document.createElement("th");

th_id.textContent = "Id";
th_name.textContent = "Name";
th_price.textContent = "Price";

tr_head.appendChild(th_id);
tr_head.appendChild(th_name);
tr_head.appendChild(th_price);

thead.appendChild(tr_head);

for(var i = 0, j = fruits.length; i < j; i++) {
    var tr_body = document.createElement("tr");

    var td_id = document.createElement("td");
    var td_name = document.createElement("td");
    var td_value = document.createElement("td");

    td_id.textContent = i;
    td_name.textContent = fruits[i].key;
    td_value.textContent = fruits[i].value;

    tr_body.appendChild(td_id);
    tr_body.appendChild(td_name);
    tr_body.appendChild(td_value);

    tbody.appendChild(tr_body);
}


tbl.appendChild(thead);
tbl.appendChild(tbody);

 console.log(tbl);
Jordan Papaleo
  • 1,463
  • 11
  • 24
0

Maybe like this:

function obj2htmltable(obj) {
    var html = '<table>';
    for (var key in obj) {
        var value = obj[key].toString();
        html += '<tr><td>' + key + '</td><td>' + value + '</tr>';
    }
    html += '</table>';
    return html;
}

If case of nested structure (objects inside object) obj2htmltable() could call itself recursively:

function obj2htmltable(obj) {
    var html = '<table>';
    for (var key in obj) {
        var item = obj[key];
        var value = (typeof(item) === 'object') ? obj2htmltable(item) : item.toString();
        html += '<tr><td>' + key + '</td><td>' + value + '</tr>';
    }
    html += '</table>';
    return html;
}
Mario Orlandi
  • 5,629
  • 26
  • 29