0

I've been working with dynamic HTML tables through JSON data for the past like two months, and it's been working great. However the only codes I've been using to make tables use array items to make a single row through .forEach(), which is fine for what I've been doing so far, but now I need something else.

For example, among more data, I have the following JSON:

 {"songs":[
 {
     "name":"Manatsu wa Dare no Mono?",
     "id":159,
     "attribute":"smile",
  },
  {
     "name":"Jimo Ai♡Mantan☆Summer Life",
     "id":160,
     "attribute":"pure"
  },
  {
     "name":"Natsu no Owari no Amaoto ga",
     "id":161,
     "attribute":"cool"
  }
]
}

Instead of making a table that would look like:

Manatsu wa Dare no Mono?    | 159 | smile
Jimo Ai♡Mantan☆Summer Life  | 160 | pure
Natsu no Owari no Amaoto ga | 161 | cool

which is what my codes do, I would instead like to have a table that would make 3 rows for every 3 items, for example, it would look like this:

Manatsu wa Dare no Mono? | Jimo Ai♡Mantan☆Summer Life | Natsu no Owari no Amaoto ga 
159                      | 160                        | 161
smile                    | pure                       | cool

I can't use .forEach() for this because I have no way to specify that I only want three columns (unless I do, and I just can't see how at all). I figured I might have to use a regular for loop, and do something like i < 3 but I honestly can't think of any way that this would make sense in terms of looping through the data the way I want to.

Is this possible at all? Any help is much appreciated.

Edit: the full JSON is here (has way more than 3 items). Basically I want to make a table of every item in this array, with one row for every three items, but it also shouldn't list every key for every item (only name, id, attribute).

0

3 Answers 3

2

You can do that using the modulus operator with the array index to create a new TR every third item, otherwise add the new TD to the previous TR.

 var yourData = {
   "songs":[
   {
     "name":"Manatsu wa Dare no Mono?",
     "id":159,
     "attribute":"smile",
  },
  {
     "name":"Jimo Ai♡Mantan☆Summer Life",
     "id":160,
     "attribute":"pure"
  },
  {
     "name":"Natsu no Owari no Amaoto ga",
     "id":161,
     "attribute":"cool"
  }
  ]
};

var s = yourData.songs;
var $tbody = $("#songs tbody");
var $tr;
    
s.forEach(function (song, i) {
  // create a new TR for the first item and every three items after
  if (i % 3 == 0) {
    $tr = $('<tr>');
    $tbody.append($tr);
  }
  $tr.append($("<td>").html(song.name + "<br>" + song.id + "<br>" + song.attribute));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id='songs'>
<tbody></tbody>
</table>

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

3 Comments

I think I'm an idiot because when I use this code all the <td>s end up outside of the <tr>s, so it just ends up being one line of cells rather than cutting every three. ;_;
Nope - I was assigning the variable $tr to the wrong thing - take another look.
Works like a charm now! Thanks so much.
1

You can grab the keys from json.songs[0] and use that for your row loop:

var $tbody = $("#songs tbody");
Object.keys(json.songs[0]).forEach(key => {
  var cells = json.songs.map(song => $("<td>").text(song[key]));
  $tbody.append($("<tr>").append(cells));
});

Edit: here's an alternate way using <div>s instead of a <table>. The number of cells per row is specified using the width of the inner <div>.

var json = {
  "songs": [{
    "name": "Manatsu wa Dare no Mono?",
    "id": 159,
    "attribute": "smile",
  }, {
    "name": "Jimo Ai♡Mantan☆Summer Life",
    "id": 160,
    "attribute": "pure"
  }, {
    "name": "Natsu no Owari no Amaoto ga",
    "id": 161,
    "attribute": "cool"
  }, {
    "name": "Jimo Ai♡Mantan☆Summer Life",
    "id": 160,
    "attribute": "pure"
  }, {
    "name": "Natsu no Owari no Amaoto ga",
    "id": 161,
    "attribute": "cool"
  }]
}

var $songs = $("#songs");
var keys = ["name", "id", "attribute"];
json.songs.forEach((song, i) => {
  var text = keys.map(key => song[key]).join("<br>");
  $songs.append($("<div>").html(text))
});
#songs div {
  display: inline-block;
  width: 33.3%;
  padding: 10px;
  box-sizing: border-box;
  vertical-align: top;
  height: 6em;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="songs">
</div>

4 Comments

I'm sorry, probably my initial query wasn't clear due to my example. While this works I meant to have a <tr> every 3 <td> specifically. This just lists everything in a single <tr>.
@Kach No it doesn't, at all. Did you look at the live example in my answer? Here's a fiddle: jsfiddle.net/khrismuc/gpkqd6aw
Sorry yes, it does do as many <tr>s as there are keys but I meant it didn't create another "batch" after 3 <td>s, so all the items were on the same row rather than cutting after 3.
@Kach I see, I was wondering about a table 160 cells wide but didn't get the "three per row". I've changed my code to what I think is a better solution than a table.
0

Here is my take - Given the very specific scenario you are encountering, I will prefer to normalize the data so that it's more convenient to work on or to extend. I prefer this approach because in the loop where we are adding the tr and td tags, it 'looks more streamline' like how a table row and cell is structured semantically.

var json = {
  "songs": [{
    "name": "Manatsu wa Dare no Mono?",
    "id": 159,
    "attribute": "smile",
  }, {
    "name": "Jimo Ai♡Mantan☆Summer Life",
    "id": 160,
    "attribute": "pure"
  }, {
    "name": "Natsu no Owari no Amaoto ga",
    "id": 161,
    "attribute": "cool"
  }]
}

var aSongs = json.songs;
var oSampleObjectStructure = aSongs[0]; //use the keys as sample
var oNormalizedStructure = {};
var sTr = '';

//normalize data format for this specific needs.
for (var sKey in oSampleObjectStructure) {
  oNormalizedStructure[sKey] = [];
  for (var i = 0; i < aSongs.length; i++) {
    oNormalizedStructure[sKey].push(aSongs[i][sKey]);
  }
}

console.log(oNormalizedStructure); //just to show you the normalized data structure

//parse using the normalized data.
for (var sKey in oNormalizedStructure) {
  sTr += '<tr>';
  for (var i = 0; i < oNormalizedStructure[sKey].length; i++) {
    sTr += '<td>' + oNormalizedStructure[sKey][i] + '</td>';
  }
  sTr += '</tr>';
}
document.getElementById('theBody').innerHTML = sTr;
table {
  width: 100%;
}

td {
  border-right: solid 1px #ccc;
}
<table>
  <tbody id="theBody"></tbody>
</table>

Hope it inspires!

1 Comment

While this works it gives me the same result as Chris G's answer (and theirs was a lot shorter, lol), I originally meant to create a new <tr> for every 3 <td>.

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.