Home > Blockchain >  Struggling with formatting nested tables in Javascript
Struggling with formatting nested tables in Javascript

Time:01-03

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>

  • Related