2

I have a JSON array that I would like to loop through to create a table.

TITLE etc would of course be the headings of the table and the associated data placed underneath.

JSON Result from PHP file

[
  {
     "TITLE":"Empire Burlesque",
     "ARTIST":"Bob Dylan",
     "COUNTRY":"USA",
     "COMPANY":"Columbia",
     "PRICE":"10.90",
     "YEAR":"1985"
  },{
     "TITLE":"Picture book",
     "ARTIST":"Simply Red",
     "COUNTRY":"EU",
     "COMPANY":"Elektra",
     "PRICE":"7.20",
     "YEAR":"1985"
  }
]

PHP

$filterText = "1985";//$_REQUEST["text"];

$filename = "xml/xml_cd.xml";
$filterHeading = "YEAR";
$filterText = "1985";//$_REQUEST["text"];

$file = simplexml_load_file($filename);

$children = $file->children();
$firstchild = $children[0];
$node = $firstchild->getName();

$result = $file->xpath('//'.$node.'['. $filterHeading . '/text()="'.$filterText.'"]');

$jsondata = json_encode($result,true);

print_r($jsondata);

I believe the solution should be in javascript but can't quite work out how to tackle the problem, being new to JSON and JAVASCRIPT.

0

4 Answers 4

5

Like this - using jQuery because it makes Ajax and subsequent processing much simpler - please note you do not have to parse the XML on the server and create JSON. You could just serve the XML to the jQuery and have similar processing:

  // here is your success from AJAX

  var tbody = $("<tbody />"),tr;
  $.each(data,function(_,obj) {
      tr = $("<tr />");
      $.each(obj,function(_,text) {
        tr.append("<td>"+text+"</td>")
      });
      tr.appendTo(tbody);
  });
  tbody.appendTo("#table1"); // only DOM insertion   

If you want to specify each field:

      tr
      .append("<td>"+obj.TITLE+"</td>")
      .append("<td>"+obj.ARTIST+"</td>")      

where the markup I use is

<table id="table1">
  <thead></thead>
</table>

Result:

const data = [
  { "TITLE": "Empire Burlesque", "ARTIST": "Bob Dylan", "COUNTRY": "USA", "COMPANY": "Columbia",   "PRICE": "10.90", "YEAR": "1985" }, 
  { "TITLE": "Picture book", "ARTIST": "Simply Red", "COUNTRY": "EU", "COMPANY": "Elektra", "PRICE": "7.20", "YEAR": "1985" }];
  
$(function() {
  const thead = $("#table1 thead");
  const tbody = $("#table1 tbody");
  let tr = $("<tr />");

  $.each(Object.keys(data[0]), function(_, key) {
    tr.append("<th>" + key + "</th>")
  });
  tr.appendTo(thead);

  $.each(data, function(_, obj) {
    tr = $("<tr />");
    $.each(obj, function(_, text) {
      tr.append("<td>" + text + "</td>")
    });
    tr.appendTo(tbody);
  });
})
td {
  border: 1px solid black;
  padding: 5px
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table id="table1">
  <thead>
  </thead>
  <tbody>
  </tbody>
</table>

Plain JS

const data = [
  { "TITLE": "Empire Burlesque", "ARTIST": "Bob Dylan", "COUNTRY": "USA", "COMPANY": "Columbia",   "PRICE": "10.90", "YEAR": "1985" }, 
  { "TITLE": "Picture book", "ARTIST": "Simply Red", "COUNTRY": "EU", "COMPANY": "Elektra", "PRICE": "7.20", "YEAR": "1985" }];
  
window.addEventListener('DOMContentLoaded', () => {
  const thead = document.querySelector("#table1 thead");
  const tbody = document.querySelector("#table1 tbody");
  
  thead.innerHTML = `<tr>
      ${Object.keys(data[0]).map(key => `<th>${key}</th>`).join('')}
    </tr>`;

  tbody.innerHTML =  data
    .map(item => `<tr>
      ${Object.values(item).map(val => `<td>${val}</td>`).join('')}
    </tr>`).join('')
})
td {
  border: 1px solid black;
  padding: 5px
}
td:nth-child(5) { text-align:right }
<table id="table1">
  <thead>
  </thead>
  <tbody>
  </tbody>
</table>

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

8 Comments

Is there a way to loop through the objects without specifying the .TITLE / .ARTIST? As the JSON file in use can change at any time.
If you have a lot of data, it might be good to do string concatenation instead of appending to the dom on every loop. You would just append once to the table after the for-loop.
how do I check that a Key is present or not present? so that later it can be replaced using the default value. for example: if (key.length == 0) {key = "-"}
.append("<td>"+(obj.TITLE || "-")+"</td>")
@mplungjan would you implement in my example? jsfiddle.net/paydjo/wLg9c6j7/6
|
1

You have an array of objects, so loop the array and target the properties you want:

for (var i = 0; i < data.length; i++) {
    console.log(data[i].title);
}

To build the table, you'll have to construct HTML within the loop and append after (quick example):

table += "<th>" + data[i].title + "</th>";

I would recommend a templating engine like MustacheJS or Angular.

4 Comments

Is there a way to do the loop without specifically calling the Headers? (.TITLE etc)
No, each time the JSON file changes, you'll have to reload. If you want live changes you'll need web sockets
You could put the loop into a function and have a parameter for the array and one for the name of your property: var myprop = 'TITLE'; for ... { ... data[i][myprop] ... } and you my change that parameter everytime you call the function.
By the way, this solution is IMO the fastest (using string concatenation instead of multiple appends to the DOM).
1

Building a table from JSON using string concatenation:

function build(target, data, columns) {
    var head = '', rows = '';
    for (int j = 0; j < columns.length; j++) {

        var cols = '';
        for (int i = 0; i < data.length; i++) {
            cols += '<td>'+data[i][columns[j]]+'</td>';
        }

        head += '<th>'+columns[j]+'</th>';
        rows += '<tr>'+cols+'</tr>';
    }

    $(target).html(
        '<table>'+
            '<thead>'+head+'</thead>'+
            '<tbody>'+rows+'</tbody>'+
        '</table>'
    );
}

Using this:

var data = [
    {
      "TITLE":"Empire Burlesque",
      "ARTIST":"Bob Dylan",
      "COUNTRY":"USA",
      "COMPANY":"Columbia",
      "PRICE":"10.90",
      "YEAR":"1985"
   },{
      "TITLE":"Picture book",
      "ARTIST":"Simply Red",
      "COUNTRY":"EU",
      "COMPANY":"Elektra",
      "PRICE":"7.20",
      "YEAR":"1985"
   }
 ]

 build('#mycontainer', data, ['TITLE', 'ARTIST', 'YEAR']);

Would result in:

<div id="mycontainer">
    <table>
        <thead>
            <th>TITLE</th>
            <th>ARTIST</th>
            <th>YEAR</th>
        </thead>
        <tbody>
            <tr>
                <td>Empire Burlesque</td>
                <td>Bob Dylan</td>
                <td>1985</td>
            </tr>
            <tr>
                <td>Picture book</td>
                <td>Simply Red</td>
                <td>1985</td>
            </tr>
        </tbody>
    </table>
</div>

Comments

0

My solution is with plain old JavaScript. For ease I'm adding some table elements to the HTML instead of creating it all from JS.

            <table id="people" class='table table-striped'>
                        <thead>
                            <th>id</th>
                            <th>Name</th>
                            <th>Age</th>
                            <th>Email</th>
                            <th>Occupation</th>
                        </thead>
                        <tbody></tbody>
                    </table>

Then in our JavaScript or JSON file, we have some data. I'm creating a factory:

var Person = function Person(id, name,age, email, occupation) {
    this.id         = id;
    this.name       = name;
    this.age        = age;
    this.email      = email;
    this.occupation = occupation;
};

Then I will create the data:

var data = [
    new Person( 1,'Bill Thompson' , 45,'[email protected]'  , 'Math Teacher' ),
    new Person( 2,'Lori Segway'   , 22,'[email protected]'  , 'Hair Stylist' ),
    new Person( 3, 'Peggy Stiller' , 31, '[email protected]'  , 'Makeup Artist' ),
    new Person( 4, 'Harry Lane'    , 62, '[email protected]', 'Company Ceo' ),
    new Person( 5, 'Michael Lowney', 40, '[email protected]' , 'Gung Fu Instructor' ),
    new Person( 6,'Paul Byrant'   , 56, '[email protected]' , 'Web Developer' )
];

Grab the DOM element like this:

var output = document.querySelector('#people tbody');

and populate the table with a forEach loop.

data.forEach(function (person) {
    var row = document.createElement('tr');
    ['id', 'name', 'age', 'email', 'occupation'].forEach(function (prop) {
        var td = document.createElement('td');
        td.appendChild(document.createTextNode(person[prop]));
        row.appendChild(td);
    });
    output.appendChild(row);
});

It's that simple. I'm using a forEach because I believe it's easier to see what's going on.

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.