简体   繁体   中英

Loading a HTML table from JSON values with JavaScript

I have a JSON file that looks like this https://pastebin.com/ushcMpwY , and I would like to load it into a HTML table that has 6 columns (group, name, registration 1, registration 2, week, half term). Here is an example of what I would like it to produce:

<table id="people">
    <tr>
        <th>Group name</th>
        <th>Name</th>
        <th>Registration 1</th>
        <th>Registration 2</th>
        <th>Week</th>
        <th>Half term</th>
    </tr>

    <!-- Where JS inserted HTML begins -->
    <tr class="9" id="HA09_000">
        <td>9</td>
        <td>Wyatt Fedlt</td>
        <td>R</td>
        <td>R</td>
        <td>0</td>
        <td>1</td>
    </tr>

    ...

    <!-- Where JS inserted HTML ends -->

</table>

It was suggested to me that I should use an OOP approach such as this one https://pastebin.com/0TRrLT6n , and while I was able to get that to work with regards to printing out the data, it didn't seem like an approach that would be very useful for making the actual table. At the moment it is very buggy. It produces a table that looks like this: http://prntscr.com/m9eh44 and I just don't know how to get it to make one like I've described above, and so I'd rather go back to a procedural approach that I understand like the one I have referenced in the Pseudo Code below.

Initially, I tried to write some code what would work like this Pseudo Code:

TABLE = GET_TABLE_BY_ID('people')
PERSON_COUNT = 0
FOR GROUP IN DATA:
    FOR PERSON IN GROUP:
        ROW = TABLE.INSERTROW(PERSON_COUNT)
        ROW.CLASSLIST.ADD(GROUP.NAME)
        ROW.ID.ADD(PERSON.ID)
        CELL = ROW.INSERTCELL(0)
        CELL.INNERHTML = GROUP.NAME
        INFO_COUNT = 0
        FOR INFO IN PERSON:
            CELL = ROW.INSERTCELL(INFO_COUNT)
            CELL.INNERHTML = INFO
            INFO_COUNT++
        PERSON_COUNT++

That resulted in some actual code like this (at that point I was just trying to print out the values since it would then be simple enough to convert it into code to generate the table).

$.getJSON("http://localhost:8000/data.json", function(data) {
    output_json(data);
});

function output_json(data) {
    var i, j, k;
    for (i = 0; i < Object.keys(data).length; i++) {
        group_ = Object.values(data)[i];
        for (j = 0; j < Object.keys(group_).length; j++) {
            person = Object.values(group_)[j];
            person_id = Object.keys(person)[0];
            console.log(Object.keys(data)[i]); // Group
            console.log(person_id); // ID
            for (k = 0; k < Object.keys(person).length; k++) {
                person_info = Object.values(person)[k][0];
                console.log(person_info); // Information
            }
        }
    }
}

I was hoping for this code to print out the data that I would like to input into the table for each person, ie their group, their name, etc. I wanted it to do this:

9

HA09_000

Wyatt Feldt

R

R

0

1

However, my code currently produces this:

9

HA09_000

{name: "Wyatt Feldt", registration_1: "R", registration_2: "R", week: 0, half_term: 1}

If someone could show me how to at least print the values then (as long as it is procedural), I'm confident I can add the table part in myself. However, if you think this really should be OOP then I would hugely appreciate it if you could explain to me how I could implement the table part as well. I know I can make this work with 4 for loops, but that's very inefficient and I'm confident it can be done in 3 much clearer loops like I've laid out in my Pseudo Code.

Thanks.

IMO a more readable/elegant solution is to separate concerns a little and use pure functions...

  1. Flatten all your data
  2. Build HTML table rows
  3. Add to table
    let rowKeys = Object.keys(data);

    // iterate over the 'first level' keys with the goal of extracting the values needed in the final objects (elemClass), while then extracting the 'second level' object (group) so that you can access its data.
    let rowsFlattened = rowKeys.reduce((acc,key) => {
            let elemClass = key,
                group = data[key];

             let people = group.reduce((acc2,groupObj)=> {
                    let elemId = Object.keys(groupObj)[0],
                        person = groupObj[elemId][0];

                        return [
                            ...acc2,
                            {
                                ...person,
                                className: elemClass,
                                id: elemId
                            }
                        ]
                },[])

                // these 'spread operators' merge either objects or arrays, in this case an array.
                return [
                    ...acc,
                    ...people
                ]

        // this '[]' is the starting accumulator, which you have access to in the 'acc' parameter above. After each iteration this 'acc' value is replaced by whatever value is returned in the previous iteration. 
        },[]);

    // 
    let rowsHTML = rowsFlattened.map(obj => {
            let { className, id, name, registration_1, registration_2, week, half_term} = obj;
            return `
                <tr class="${className}" id="${id}">
                    <td>${className}</td>
                    <td>${name}</td>
                    <td>${registration_1}</td>
                    <td>${registration_2}</td>
                    <td>${week}</td>
                    <td>${half_term}</td>
                </tr>
            `
        })  

        $('#people').html(rowsHTML);

My solution is a little long so please see the below jsFiddle...

https://jsfiddle.net/u1ekga7y/

I'm guessing you want the person info to be in an array? Add another loop to go through the person_info object keys and values..

        for (k = 0; k < Object.keys(person).length; k++) {
            person_info = Object.values(person)[k][0];
            console.log(person_info); // Information
        }

To

        var person_info_data = [];
        for (k = 0; k < Object.keys(person).length; k++) {
            person_info = Object.values(person)[k][0];
            for (l = 0; l < Object.keys(person_info).length; l++) {
                person_info_data.push(Object.values(person_info)[l])
            }
            console.log(person_info_data); // Information
        }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM