0

I have worked on looping through json and creating a tr, td, and content then appended them together.

I tried using the same technique for looping through each property inside of each object however It's not working the same way.

How do I create json and loop through it to individual table rows that include each json property?

For example I want to loop through food[0] and post food[0].serving, etc

http://jsbin.com/mohamavemo/3/edit?html,js,console,output

Thank you for your time --Brian Story

2
  • Post your problematic code please. What seems to be the problem? Commented Nov 29, 2014 at 13:18
  • Did you read the post? I added a jsbin link with my full source. Commented Nov 29, 2014 at 14:01

4 Answers 4

1

I think your question is the ideal use case for a JS template library. Below is given the solution with handlebars: http://handlebarsjs.com/.

You only have to write your template:

<script id="template" type="text/x-handlebars-template">
    {{#items}}
            <tr><td>{{item}}</td><td>{{serving}}</td></tr>
    {{/items}}
</script>

And then to compile it and inject it in your HTML page:

    var tplScript = $("#template").html();
    var template = Handlebars.compile (tplScript);
    $("#genItems").html(template(food));

Below is the full code:

<script src="lib-js/jquery-1.11.1.min.js"></script> 
<script src="lib-js/handlebars-v2.0.0.js"></script>
<body>
<table>
    <thead>
    <tr>
        <th>Items</th>
        <th>Servings</th>
    </tr>
    </thead>
    <tbody id="genItems">
    <!-- tr generated here -->
    </tbody>
</table>

<script id="template" type="text/x-handlebars-template">
    {{#items}}
            <tr><td>{{item}}</td><td>{{serving}}</td></tr>
    {{/items}}
</script>
<script>
    var food = {};
    food.items = [{
            "item" : "Bread",
            "serving" : "1",
            "value" : "slice",
            "amount" : 16,
            "daily" : 2,
            "used" : 8
        },
        {
            "item" : "Cheese",
            "serving" : "1",
            "value" : "oz",
            "amount" : 16,
            "daily" : 2,
            "used" : 8
        },
        {
            "item" : "Crackers",
            "serving" : "1",
            "value" : "oz",
            "amount" : 16,
            "daily" : 2,
            "used" : 8
        }];

    var tplScript = $("#template").html();
    var template = Handlebars.compile (tplScript);
    $("#genItems").html(template(food));
</script>

Note that JQuery is just used for convenience here.

Pros/Cons of this solution over a pure JS solution:

Pros:

  • very concise
  • clean: you don't mix your template with business logic
  • preparation for next generation of web applications

Cons:

  • not as performant as pure JS

Fiddle: http://jsfiddle.net/tr22rfmd/1/

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

1 Comment

Thank you, this was very helpful for getting me in the right direction.
0

Some sourcecode would help..but here are some pointers..

Run the JSON loop and populate the JSON property into an ArrayList. Once the entire JSON is processed, pass the ArrayList as an adapter for your table rows.

Comments

0

I have updated your js like this.

// Create json array that can be looped through
var food = [{
  "item" : "Bread",
  "serving" : "1",
  "value" : "slice",
  "amount" : 16,
  "daily" : 2,
  "used" : 8 
},
{
  "item" : "Cheese",
  "serving" : "1",
  "value" : "oz",
  "amount" : 16,
  "daily" : 2,
  "used" : 8
},
{
  "item" : "Crackers",
  "serving" : "1",
  "value" : "oz",
  "amount" : 16,
  "daily" : 2,
  "used" : 8
}];

// set item to number of food data
var item = food.length;

// set ID locations in dom

var genItems = document.getElementById("genItems");
// Generate header
if(item > 0)
  {
    var tr = document.createElement('tr'); 
    for(var prop in food[item-1])
    {       
      var td = document.createElement('td');        td.appendChild(document.createTextNode(prop));
      tr.appendChild(td);
    }
    genItems.appendChild(tr);
  }

// Loop though items and create table rows
for(item; item > 0; item--){

  // console log items to confirm I'm getting them
  console.log(food[(item-1)].item + " " + food[(item-1)].serving +" "+ food[(item-1)].value);

  // create table row element
  var tr = document.createElement('tr');

  // create table data 

  for(var prop in food[item-1])
  {  
  var td = document.createElement('td');  
  td.appendChild(document.createTextNode(food[item-1][prop]));
  tr.appendChild(td);
  }
  // append td to tr


  //  Apend tr to table id genItems
  genItems.appendChild(tr);

}

HTML

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>JS Bin</title>
</head>
<body>
    <table>
      <tbody id="genItems">
        <!-- tr generated here -->
      </tbody>
    </table>
</body>
</html>

Comments

0

The issue is that the outer structure is an array while the elements are objects. Objects are inherently unordered and can be iterated over with https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...in, but this is not going to reliably do what you want. I see two options:

Explicit dereferencing: Use the syntax you have above and extract the fields by name in each row. food[ix].serving, etc. This is nice and simple and you'd only have to do the mapping of the fields once so from the sample this should not take a notable effort. recommended in some form

Use a second array to define fields: This is more complicated and doesn't really provide any advantage over the explicit option in the sample given but is more of an answer to the question. It would be useful in cases where there are a lot of fields and/or an external schema. The field variable could then be used to access the appropriate member of the row. This would be similar to:

var fields = ['item', 'serving'];
var currentField;
for (fieldNum = 0; fieldNum < fields.length; fieldNum++) {
  currentField = fields[fieldNum];
  food[ix][currentField]; //Do whatever
  //Or probably assign the array element to a temp variable also
  row[currentField];
}

Comments

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.