简体   繁体   中英

Displaying array of objects dynamically in table columns - Javascript

I am attempting to create an appointment slot selection grid. I have all the appointments grouped into dates. I want to display the array of Objects below as a clickable grid. I have everything I need but I'm having difficulty displaying it in columns. My current output: 在此处输入图片说明

As you can see it is displaying the correct appointments next to the correct date header however its adding the next one in the same row and so on. I want each date and its corresponding appointments to be displayed in separate columns. Date header at the top with appointments listed below. I'm just using a main.js file and an index.html file.

Grouped appointment slots array below looks something like this:

2020-09-25: [{0:{AppointmentDateTime: "2020-09-25T13:00:00Z"}}]
2020-09-28: [{0:{AppointmentDateTime: "2020-09-28T08:00:00Z"}},{1:{AppointmentDateTime: "2020-09-28T10:30:00Z"}}, {2:{AppointmentDateTime: "2020-09-28T11:00:00Z"}}]
2020-09-29: [{0:{AppointmentDateTime: "2020-09-29T08:00:00Z"}},{1:{AppointmentDateTime: "2020-09-29T09:00:00Z"}}, {2:{AppointmentDateTime: "2020-09-29T11:00:00Z"}}]

Here is what I have so far:

let result = await response.json();
let groupedAppointments = {}

result.forEach((item) => {
    const date = item.AppointmentDateTime.split('T')[0]
    if (groupedAppointments[date]) {
        groupedAppointments[date].push(item);
    } else {
        groupedAppointments[date] = [item];
    }
})


var grid = clickableGrid(groupedAppointments, groupedAppointments, function(el, item) {
    console.log("You clicked on element:", el);
    selectedAppointment = item.AppointmentDateTime;
    console.log(selectedAppointment);
    el.className = 'clicked';
    if (lastClicked) lastClicked.className = '';
    lastClicked = el;
});

document.getElementById("clickable-grid").appendChild(grid);
function clickableGrid(groupedAppointments, index, callback) {
    var i = 0;
    var grid = document.createElement('table');

    grid.className = 'grid';

    Object.keys(groupedAppointments).forEach((item) => {

        var days = groupedAppointments[item];
        var tableRowHeader = grid.appendChild(document.createElement('tr'));
        var th = tableRowHeader.appendChild(document.createElement('th'));
        th.innerHTML = item;

        days.forEach((item) => {

            var tr = grid.appendChild(document.createElement('tr'));
            //var rowHeader = tr.appendChild(document.createElement('th'))
            var cell = tr.appendChild(document.createElement('td'));
            //rowHeader.innerHTML = item.SlotName;
            cell.innerHTML = item.AppointmentDateTime;
            cell.addEventListener('click', (function(el, item) {
                return function() {
                    callback(el, item);
                }
            })(cell, item), false);
        })

    })

    return grid;
}

I hope this is enough detail. Any questions just ask. All help greatly appreciated.

updated output:

在此处输入图片说明

在此处输入图片说明

You shouldn't create a tr for each appointment.

You need two loops. One loop creates the header row with all the dates.

Then you loop over the array indexes to create the data rows. Within that, you have a nested loop for each date, filling in that column in the row. Since dates will have different numbers of appointments, you need to check if the current date has that many appointments. If it is you fill in the cell, otherwise you leave it empty.

 function clickableGrid(groupedAppointments, callback) { var i = 0; var grid = document.createElement('table'); grid.className = 'grid'; var longest = 0; var headerRow = grid.appendChild(document.createElement('tr')); Object.entries(groupedAppointments).forEach(([item, day]) => { if (day.length > longest) { longest = day.length; } var th = headerRow.appendChild(document.createElement('th')); th.innerHTML = item; }); for (let i = 0; i < longest; i++) { var tr = grid.appendChild(document.createElement('tr')); Object.values(groupedAppointments).forEach(item => { var cell = tr.appendChild(document.createElement('td')); if (i < item.length) { let time = item[i].AppointmentDateTime.split('T')[1].split('Z')[0]; cell.innerHTML = time; cell.addEventListener('click', (function(el, item) { return function() { callback(el, item); } })(cell, item[i]), false); } }); } return grid; } var data = { "2020-09-25": [{ AppointmentDateTime: "2020-09-25T13:00:00Z" }], "2020-09-28": [{ AppointmentDateTime: "2020-09-28T08:00:00Z" }, { AppointmentDateTime: "2020-09-28T10:30:00Z" }, { AppointmentDateTime: "2020-09-28T11:00:00Z" }], "2020-09-29": [{ AppointmentDateTime: "2020-09-29T08:00:00Z" }, { AppointmentDateTime: "2020-09-29T09:00:00Z" }, { AppointmentDateTime: "2020-09-29T11:00:00Z" }] }; document.body.appendChild(clickableGrid(data, function(cell, date) { console.log("You clicked on " + date.AppointmentDateTime); }));

It looks like your table is all over the place, you create 2 table rows when actually you need to use only one for every date (with both the th and the appointments) and you only need to go to a new row when a new date is presented. I've changed some namings to be more precise (item doesn't tell a lot about what it is, plus it gets confusing when you use the same name for different params). My commented-out lines are marked with a * .

function clickableGrid(groupedAppointments, index, callback) {
    var i = 0;
    var grid = document.createElement('table');

    grid.className = 'grid';

    Object.keys(groupedAppointments).forEach((date) => {

        //*var days = groupedAppointments[key]; --> since you don't copy and just refferencing a memory slot
        var tr = grid.appendChild(document.createElement('tr')); // renamed to tr because you need to have only one row, both for the header and the data
        var th = tr.appendChild(document.createElement('th'));
        th.innerHTML = date;

        groupedAppointments[date].forEach((appointment) => {

            //*var tr = grid.appendChild(document.createElement('tr')); --> cell and table hadder are in the same row
            //var rowHeader = tr.appendChild(document.createElement('th'))
            var cell = tr.appendChild(document.createElement('td'));
            //rowHeader.innerHTML = appointment.SlotName;
            cell.innerHTML = appointment.AppointmentDateTime;
            cell.addEventListener('click', (function(el, appointment) {
                return function() {
                    callback(el, appointment);
                }
            })(cell, appointment), false);
        })

    })

    return grid;
}

Hope it helped :)

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