1

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 class="map">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 class="graph">Graph</div>

2
  • You haven't put the inner tables in td elements. Commented Jan 2, 2022 at 17:30
  • Thanks! That fixed it. I'm sorry you had to look through the code for such an obvious error. I'd been staring at it for hours and hadn't seen it. Commented Jan 2, 2022 at 18:02

2 Answers 2

1

As JMP pointed out, I failed to put the nested tables in a TD element before assigning them to the table row.

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

Comments

1

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 tr. 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 class="map">Map</div>
<div id="tideTable"></div>
<div class="graph">Graph</div>

1 Comment

Wow, thanks trincot. I was finding it very complex and error prone trying to keep my place between all of the element creations and appending. I think this really helps me simplify it. Cheers.

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.