0

I have a JSON file here: https://next.json-generator.com/api/json/get/E1qcwkNxr

and I want to use it to create a table. Using jQuery I get the response Array and map some values to build my table body cells:

        var data = $.getJSON('https://next.json-generator.com/api/json/get/E1qcwkNxr', function (response) {

            // map JSON to local arrays and define local vars
            var rows = response.map(function (r) {
                return [
                    r.age,
                    r.index,
                    r.registered,
                    r.balance,
                    r.eyeColor
                ];
            });
        });

I want to do the same thing with the keys because I want to build the thead cells with that data. There's a way to do it? Object.keys(response[0]); log me all the keys in the object, How can I map only the key I want to use?

5
  • Sorry if I'm misunderstanding the question, but are you trying to limit the Object.keys to those that you've defined in the map function (age, index, registered, balance, eyeColor?) Commented Jun 9, 2018 at 1:28
  • Yes, i need This thing Commented Jun 9, 2018 at 1:31
  • I'm curious - if you know the keys upfront, why do you need to call Object.keys? Is it to reduce duplication of the key names (in map, and then thead building)? Or, another reason? Commented Jun 9, 2018 at 1:38
  • @Jack look at the sample JSON file: I have 12 entries, and I want to use only five of them in this table. In another table I'm going to use different entries of the same file Commented Jun 9, 2018 at 1:43
  • Here's some JavaScript I threw together really quickly: jsfiddle.net/jLe4ym2w - Would you be using Object.keys to generate the table header? (Edit: Rendering the other table: jsfiddle.net/jLe4ym2w/1) Commented Jun 9, 2018 at 2:51

2 Answers 2

1

To answer your question regarding Object.keys, you would need to filter against a known set.

For example:

let keysToRender = ['index', 'age'];
Object.keys(response[0]).filter(key => { return ~keysToRender.indexOf(key) })

Here's a solution I threw together (it's based on the fiddle link I posted in my comments to you, but cleaned up) which uses map. Personally, I prefer map over $.each (for this problem) as there's slightly less overhead.

Fiddle: http://jsfiddle.net/x3p79jfs/

Edit: Here's a fiddle that maintains order based on response (as you mentioned in the other comment) - http://jsfiddle.net/x3p79jfs/1/

Hope it helps!

$.getJSON('https://next.json-generator.com/api/json/get/E1qcwkNxr', function(res) {
    // Extracts values from response
    const getModelFromKeys = (res, keys) => {
        return res.map(item => {
            return keys.map(key => {
                return item[key];
            });
        });
    };

    // Build template to append
    const buildTableFromModel = (header, body) => {
        let reducer = (arr, func, acc) => {
            return arr.reduce(func, acc);
        };

        let getTemplateCell = (template, item) => template + `<td>${item}</td>`;
        let getTemplateRow = (template, item) => template + `<tr>${reducer(item, getTemplateCell, ``)}</tr>`;
        
        return `
            <table><thead><tr>
            ${reducer(header, getTemplateCell, ``)}
            </tr></thead><tbody>
            ${reducer(body, getTemplateRow, ``)}
            </tbody></table>
        `
    };

    // Our expected set of keys to render (note first, last names which do not exist)
    let pii_table = ['age', 'index', 'first_name', 'last_name', 'registered', 'balance', 'eyeColor'];

    // Filter expected keys against ajax response
    // let filteredKeys = Object.keys(res[0]).filter(key => {
    //    return ~pii_table.indexOf(key);
    // });

    // Filter expected keys against ajax response
    let responseKeys = Object.keys(res[0]);
    let filteredKeys = pii_table.filter(key => {
        return ~responseKeys.indexOf(key);
    });

    // Build Table Model From Filtered Keys
    let firstTableModel = getModelFromKeys(res, filteredKeys);
    
    // Append table to Body
    document.body.innerHTML += buildTableFromModel(filteredKeys, firstTableModel);
});
td {
    padding: 3px;
    text-align: center;
}
thead {
    color: white;
    background-color: #777;
}
tr:nth-child(2n) {
    background-color: #ccc;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

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

1 Comment

thank you, it works, I will use your example in my future works too. Thanks a lot!
0

I would suggest you use $.each() and not $.map(). Something like this:

var rows = [];
$.getJSON('https://next.json-generator.com/api/json/get/E1qcwkNxr', function (response) {
  $.each(response, function(i, x){
    var obj = {};
    var s = ["age", "index", "registered", "balance", "eyeColor"];
    $.each(x, function(k, v){
      if(s.indexOf(k) >= 0){
        obj[k] = v;
      }
    });
    rows.push(obj);
  });
});

Now you will have a clean array of Objects that has both Keys and Values. You can then use it to build your table.

var $table = $("<table>");
$("<thead>").appendTo($table);
$("<tr>").appendTo($("thead", $table));
$.each(rows[0], function(key, val){
  $("<th>").html(key).appendTo($("thead tr", $table));
});
var $tbody = $("<tbody>").appendTo($table);
$.each(rows, function(ind, row){
  var $trow = $("<tr>").appendTo($tbody);
  $.each(row, function (item){
    $("<td>").html(item).appendTo($trow);
  });
});

Working Example: https://jsfiddle.net/Twisty/xv4kzy8L/

Update

If you need the the table to display in a specific sort, you can do this with your Array of key names. Then display the results in a specific order:

var headers = ["age", "index", "registered", "balance", "eyeColor"];
var $table = $("<table>");
$("<thead>").appendTo($table);
$("<tr>").appendTo($("thead", $table));
$.each(headers, function(key, val){
  $("<th>").html(val).appendTo($("thead tr", $table));
});
var $tbody = $("<tbody>").appendTo($table);
$.each(rows, function(ind, row){
  var $trow = $("<tr>").appendTo($tbody);
  $.each(headers, function (k, i){
    $("<td>").html(row[i]).appendTo($trow);
  });
});

Hope that helps.

2 Comments

I try your code, but I want the keys to be sorted like the content row cells (age in the forst column, index in the second and so on..). This way the array is not sorted like the content
@ufollettu You can do that if you choose. You can either ensure it is stored in the order you'd prefer, or better, display it in the table in the order you'd prefer.

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.