I am trying to populate a table with JS. I have created the table layout in HTML as a guide and I am now trying to recreate and populate an identical table using data from an array. I just can't get it to format correctly even though my code should create the same table. Can anyone identify where I am going wrong please?
var tideTableData = [{
date: "Sat, 12 Dec, 2021",
moon: "Full Moon",
sunrise: "08:17",
sunset: "16:10",
tides: [{
time: "11:23",
height: "1.5"
}, {
time: "11:24",
height: "1.6"
}, {
time: "11:25",
height: "1.7"
}, {
time: "11:26",
height: "1.8"
}]
},
{
date: "Sun, 13 Dec, 2021",
moon: "Waning Crescent",
sunrise: "08:15",
sunset: "16:12",
tides: [{
time: "10:23",
height: "2.5"
}, {
time: "10:24",
height: "2.6"
}, {
time: "10:25",
height: "2.7"
}, {
time: "10:26",
height: "2.8"
}]
},
]
buildTable()
function buildTable() {
const headingText = ["Date", "Tides", "Daylight"];
var tideTableDiv = document.getElementById("tideTable");
var tideTable = document.createElement('table');
tideTable.style = "width=100%; float: left;";
//create headings
var headings = document.createElement("tr")
for (var i = 0; i < headingText.length; i ) {
var th = document.createElement('th');
th.innerHTML = headingText[i];
headings.appendChild(th)
}
tideTable.appendChild(headings)
//build table from data
for (var i = 0; i < tideTableData.length; i ) {
var tideTableRow = document.createElement('tr');
//day table
var dayTable = document.createElement('table');
var dtHead = document.createElement('th');
dtHead.innerHTML = tideTableData[i].date
dayTable.appendChild(dtHead)
row = document.createElement("tr");
var dtMoon = document.createElement('td');
dtMoon.innerHTML = tideTableData[i].moon
row.appendChild(dtMoon)
dayTable.appendChild(row)
tideTableRow.appendChild(dayTable)
//tides table
var tidesTable = document.createElement('table');
for (var j = 0; j < tideTableData[i].tides.length; j ) {
var tideRow = document.createElement("tr");
var tideTime = document.createElement("td");
var tideHeight = document.createElement("td");
tideTime.innerHTML = tideTableData[i].tides[j].time
tideRow.appendChild(tideTime)
tideHeight.innerHTML = tideTableData[i].tides[j].height
tideRow.appendChild(tideHeight)
tidesTable.appendChild(tideRow)
}
console.log(tidesTable)
tideTableRow.appendChild(tidesTable)
//daylight table
var dayLightTable = document.createElement('table');
var dayLightTableRow = document.createElement('tr');
var sunrise = document.createElement('td');
var sunset = document.createElement('td');
sunrise.innerHTML = "Sunrise at " tideTableData[i].sunrise
dayLightTableRow.appendChild(sunrise)
dayLightTable.appendChild(dayLightTableRow)
sunset.innerHTML = "Sunset at " tideTableData[i].sunset
dayLightTableRow = document.createElement('tr');
dayLightTableRow.appendChild(sunset)
dayLightTable.appendChild(dayLightTableRow)
tideTableRow.appendChild(dayLightTable)
//add a row containing tables to Tide Table
tideTable.appendChild(tideTableRow)
}
tideTableDiv.appendChild(tideTable)
}
function addTides() {
var tideDetails = document.getElementById("tideDetails");
var tideRow = tideDetails.insertRow(-1);
var time = tideRow.insertCell(0);
var height = tideRow.insertCell(1);
time.innerHTML = "13:23";
height.innerHTML = "1.45";
}
table,
th {
table-layout: auto;
border: 1px solid black;
vertical-align: top;
}
td {
vertical-align: top;
}
div.map {
width: 500px;
margin: auto;
border: 3px solid #73AD21;
float: left;
}
div.graph {
max-width: 500px;
margin: auto;
border: 3px solid #73AD21;
float: left;
}
<div >Map</div>
<div id="tideTable">
<table id="tides" style="width=20%; float: left;">
<tr>
<th>Date</th>
<th>Tides</th>
<th>Daylight</th>
</tr>
<tr>
<td>
<table>
<th>20 July, 2021</th>
<tr>
<td>Full Moon</td>
</tr>
</table>
</td>
<td>
<table>
<tr>
<td>11:45</td>
<td>4.23</td>
</tr>
<tr>
<td>12:45</td>
<td>1.29</td>
</tr>
<tr>
<td>13:45</td>
<td>3.99</td>
</tr>
</table>
</td>
<td>
<table>
<tr>
<td>Sun rises at: 08:23</td>
</tr>
<tr>
<td>Sun sets at: 16:01</td>
</tr>
</table>
</td>
</tr>
<tr>
<td>
<table>
<th>20 July, 2021</th>
<tr>
<td>Full Moon</td>
</tr>
</table>
</td>
<td>
<table>
<tr>
<td>11:45</td>
<td>4.23</td>
</tr>
<tr>
<td>12:45</td>
<td>1.29</td>
</tr>
<tr>
<td>13:45</td>
<td>3.99</td>
</tr>
</table>
</td>
<td>
<table>
<tr>
<td>Sun rises at: 08:23</td>
</tr>
<tr>
<td>Sun sets at: 16:01</td>
</tr>
</table>
</td>
</tr>
</table>
</div>
<div >Graph</div>
CodePudding user response:
As JMP pointed out, I failed to put the nested tables in a TD element before assigning them to the table row.
CodePudding user response:
The code can become quite complex like this. I would suggest using some helper functions so you avoid code repetition with sequences of createElement
, innerHTML
, appendChild
.
You had some invalid HTML, with td
as a direct child of table
, and table
as direct child of td
. Also some invalid CSS where =
should be :
. I would suggest to move any CSS to the <style>
element, avoiding inline styling.
Here is a suggestion:
// Helper function
function element(tag, ...children) {
const elem = document.createElement(tag);
if (typeof children[0] === "string") {
elem.textContent = children[0];
} else {
for (let child of children) {
elem.appendChild(child);
}
}
return elem;
}
// ...and the same focused to specific elements:
const td = text => element('td', text);
const th = text => element('th', text);
const tr = (...cells) => element('tr', ...cells);
const table = (...rows) => element('table', ...rows);
// Your function adapted:
const buildTable = tideTableData => table(
tr(th("Date"), th("Tides"), th("Daylight")),
...tideTableData.map(({date, moon, sunrise, sunset, tides}) =>
tr(
td(
table(
tr(th(date)),
tr(td(moon))
)
),
td(
table(
...tides.map(({time, height}) =>
tr(td(time), td(height))
)
)
),
td(
table(
tr(td("Sunrise at " sunrise)),
tr(td("Sunset at " sunset))
)
)
)
)
);
let tideTableData = [{
date: "Sat, 12 Dec, 2021",
moon: "Full Moon",
sunrise: "08:17",
sunset: "16:10",
tides: [{
time: "11:23",
height: "1.5"
}, {
time: "11:24",
height: "1.6"
}, {
time: "11:25",
height: "1.7"
}, {
time: "11:26",
height: "1.8"
}]
},
{
date: "Sun, 13 Dec, 2021",
moon: "Waning Crescent",
sunrise: "08:15",
sunset: "16:12",
tides: [{
time: "10:23",
height: "2.5"
}, {
time: "10:24",
height: "2.6"
}, {
time: "10:25",
height: "2.7"
}, {
time: "10:26",
height: "2.8"
}]
},
];
document.getElementById("tideTable")
.appendChild(buildTable(tideTableData));
table,
th {
table-layout: auto;
border: 1px solid black;
vertical-align: top;
}
td {
vertical-align: top;
}
div.map {
width: 500px;
margin: auto;
border: 3px solid #73AD21;
float: left;
}
div.graph {
max-width: 500px;
margin: auto;
border: 3px solid #73AD21;
float: left;
}
#tideTable > table {
width: 100%;
float: left;
}
<div >Map</div>
<div id="tideTable"></div>
<div >Graph</div>