1

I'm trying to generate a table from some JSON data.

What i'm trying to get is basically a list of publishers, each of that publisher's Authors, and each of that authors book details. So using the JSON below it would look something like:

Publisher      |  Author     |  BookDetails
-------------------------------------
Random House   |  John Smith |  Provided, 3, fiction
Penguin        |  William S  |  Not Provided, 5, fiction

A publisher will have more than one author and an author may have more than one book Details, in which case it would look like:

Publisher      |  Author        |  BookDetails
-------------------------------------
Random House   | John Smith     | Provided, 3, fiction
               |                | Another, John Smith Book
Penguin        | William S      | Not Provided, 5, fiction
               | Another Author | Another Authors details
               |                | Second book by another author

My JSON looks like:

 JSONCollection = {
                       "genres": [{
                           "genre": "Horror",
                               "publishers": [{
                               "publisherName": "Random House",
                                   "authors": [{
                                   "authorName": "John Smith",
                                       "bookDetails": [{
                                       "Blurb": "Provided",
                                           "Review": 3,
                                           "Type": "Fiction"
                                   }]
                               }]
                           }]
                       }, {
                           "genre": "Romance",
                               "publishers": [{
                               "publisherName": "Penguin",
                                   "authors": [{
                                   "authorName": "William Shakespeare",
                                       "bookDetails": [{
                                       "Blurb": "Not Provided",
                                           "Review": 5,
                                           "Type": "Fiction"
                                   }]
                               }]
                           }]
                       }]
                   }

The code i'm using (just to get the Publisher/author to work so far) is:

  var table = $('#dataTable')
           var table_thead = table.find('thead')
           table_thead.empty()
           var tr_head = $('<tr>')
               .append($('<th>').text('publishers'))
               .appendTo(table_thead)
           var table_tbody = table.find('tbody')
           table_tbody.empty()
           var tr_body = $('<tr>')
           for (var i = 0; i < JSONCollection.genres.length; i++) {
               for (j = 0; j < JSONCollection.genres[i].publishers.length; j++) {
                   tr_body.append($('<td />').text(this.publisherName))
                       .appendTo(table_tbody)
                   for (k = 0; k < JSONCollection.genres[i].publishers[j].authors.length; k++) {
                       tr_body.append($('<td />').text(this.authorName))
                           .appendTo(table_tbody)
                   }
               }
           }

But it doesn't seem to be working, the Publisher header is generated and then nothing after that, i'm not receiving any errors in the console. Any ideas where i'm going wrong?

Here's a fiddle: http://jsfiddle.net/hE52x/

Thanks

Hulaz
  • 257
  • 1
  • 3
  • 13
  • You could create all content and append at last. You can see an example here: http://stackoverflow.com/a/8749347/3450707 – NEOLPAR May 21 '14 at 11:27

5 Answers5

3

I think what you need is this Fiddle

var table = $('#dataTable');
var table_thead = $('#dataTable thead');
var table_tbody = $('#dataTable tbody');
var buffer="";
table_thead.html('<th>publishers</th><th>Authors</th>');

for (var i = 0; i < JSONCollection.genres.length; i++) {
    buffer+='<tr>';
    for (j = 0; j < JSONCollection.genres[i].publishers.length; j++) {
        buffer+='<td>'+JSONCollection.genres[i].publishers[j].publisherName+'</td>';
        buffer+='<td>';
        for (k = 0; k < JSONCollection.genres[i].publishers[j].authors.length; k++) {
            buffer+=(k==0?'':', ')+JSONCollection.genres[i].publishers[j].authors[k].authorName;
        }
        buffer+='</td>';
    }
    buffer+='</tr>';

}
table_tbody.html(buffer);
CME64
  • 1,673
  • 13
  • 24
  • This is great, my only question is, say i have 2 authors in Penguin, they appear next to each other, is there a way of having it display underneath the previous author 'Shakespeare' just because when i add the bookdetails i want to be able to show which books belong to which author. – Hulaz May 21 '14 at 12:04
  • @Hulaz ah yes, I added a comma between multiple authors. just replace it with a new line "\n",, if you want to add them as cells however, you can use colspan on the publisher's td equal to the number of authors and append the tds around the authornames inside the loop – CME64 May 21 '14 at 12:24
  • @Hulaz in order to use '\n' inside table cells you have to use this style `td { white-space:pre }` – CME64 May 21 '14 at 12:40
2

I have modified the Fiddle here Fiddle

in the fiddle replaced

this.publisherName with JSONCollection.genres[i].publishers[j].publisherName

Madhu
  • 2,416
  • 3
  • 15
  • 33
2

Instead i used $.each() to do this:

$.each(JSONCollection.genres, function (i, item) {
    $.each(item.publishers, function (i, item) {
        tr_body.append($('<td />').text(item.publisherName)).appendTo(table_tbody);
        $.each(item.authors, function (i, item) {
            tr_body.append($('<td />').text(item.authorName)).appendTo(table_tbody);                           
        });
    });
});

Demo


As a side note:

A table only can have <thead>, <tbody> as a direct child. The correct markup should be follow like this:

<h2>Books</h2> <!--This should not be a direct child of table-->

<table id="dataTable">
  <thead></thead>
  <tbody></tbody>
</table>
Jai
  • 74,255
  • 12
  • 74
  • 103
2

here i have tuned your code a bit

Jquery Code:

                JSONCollection = {
                   "genres": [{
                       "genre": "Horror",
                           "publishers": [{
                           "publisherName": "Random House",
                               "authors": [{
                               "authorName": "John Smith",
                                   "bookDetails": [{
                                   "Blurb": "Provided",
                                       "Review": 3,
                                       "Type": "Fiction"
                               }]
                           }]
                       }]
                   }, {
                       "genre": "Romance",
                           "publishers": [{
                           "publisherName": "Penguin",
                               "authors": [{
                               "authorName": "William Shakespeare",
                                   "bookDetails": [{
                                   "Blurb": "Not Provided",
                                       "Review": 5,
                                       "Type": "Fiction"
                               }]
                           }]
                       }]
                   }]
               }

               var table = $('#dataTable')
                var table_thead = table.find('thead')
                table_thead.empty()
                var tr_head = $('<tr>')
                   .append($('<th>').text('Publishers'))
                   .append($('<th>').text('Author'))
                   .appendTo(table_thead)
                var table_tbody = table.find('tbody')
                table_tbody.empty()
                var tr_body = $('<tr>')
                for (var i = 0; i < JSONCollection.genres.length; i++) {
                   var tr_body = $('<tr>');
                   for (j = 0; j < JSONCollection.genres[i].publishers.length; j++) {
                       $this = JSONCollection.genres[i].publishers[j];
                       alert(JSONCollection.genres[i].publishers[j].publisherName);
                       tr_body.append($('<td />').text($this.publisherName))
                           .appendTo(table_tbody)
                       for (k = 0; k < JSONCollection.genres[i].publishers[j].authors.length; k++) {
                           $this = JSONCollection.genres[i].publishers[j].authors[k];
                           tr_body.append($('<td />').text($this.authorName))
                               .appendTo(table_tbody)
                       }
                   }
               }

LIVE DEMO:

http://jsfiddle.net/dreamweiver/hE52x/19/

Happy Coding :)

dreamweiver
  • 6,002
  • 2
  • 24
  • 39
  • This is great, my only question is, say i have 2 authors in Penguin, they appear next to each other, is there a way of having it display underneath the previous author 'Shakespeare' just because when i add the bookdetails i want to be able to show which books belong to which author. So shakespear has 3 book and the new author only has 2, i'd like to have each author separated, a bit like my example in the question, is that possible? – Hulaz May 21 '14 at 12:04
  • @Hulaz: well you can add a break tag after each author details ,``. http://jsfiddle.net/dreamweiver/hE52x/29/ – dreamweiver May 21 '14 at 12:19
1

Four loops are needed to achieve this. I used $.each() to achieve this.

The first loops through the genres, the second through the publishers, the third though the authors and the last through book details. It will take care of publishers having more than one author and one author having more than one book/title.

The initial HTML for the table is as follows:

<table border="1" cellpadding="5" cellspacing="0" id="dataTable">
    <thead>
        <tr>
            <td>Publisher</td>
            <td>Author</td>
            <td>Book Details</td>
        </tr>
    </thead>
    <tbody></tbody>
</table>

The jQuery code is very as follows:

var tbody = $('#dataTable').find('tbody'),
    tr = $('<tr/>'),
    td = $('<td/>'),
    genres = JSONCollection.genres,
    row;
$.each(genres, function(index, genre) {
    $.each(genre.publishers, function(i,publisher) {
        $.each( publisher.authors, function(j, author) {
            row = tr.clone().html( td.clone().html( publisher.publisherName ) )
            .append( td.clone().html( author.authorName ) ).append( td.clone() );
            $.each(author.bookDetails, function(l,book) {
                row.find( 'td' ).eq( 2 ).append( (l>0)?'<br>':'' )
                .append( book.Blurb + ', ' + book.Review + ', ' + book.Type );
            });
            row.appendTo( tbody );
        });
    });
});

JS FIDDLE DEMO

EDIT

The demo has been adjusted to show how the code would handle multiple authors and books. The code was slightly adjusted. A CSS rule was added too.

PeterKA
  • 24,158
  • 5
  • 26
  • 48