0

apologies for how simple this question is.... function tablesfromDb(); iterates and correctly generates data from the data array above- in console.log , however the javaScript table generator only displays the last iteration. Whhhhhyyyyyyy does the javascript dynamic HTML table generator not display all the iterations as in console.log ??????? It's taken me 3 days to get to this point, and I can't get past this....

    var data = 
    [
        {
          "deviceOne":
            {
              "input": ["oneInOne", "oneInTwo","oneInThree","oneInFour"],
              "output": ["oneOutOne", "oneOutTwo", "oneOutThree"]
            }
        },
        {
            "deviceTwo":
              {
                "input": ["twoInOne", "twoInTwo","twoInThree","twoInFour"],
                "output": ["twoOutOne", "twoOutTwo", "twoOutThree", "twoOutFour", "twoOutFive"]
              }
          }
    ]

function tablesFromDb(){

  for(j=0; j<data.length; j++){
    var tableTop = "<form><table>";
    var tableHeader = "<tr><th>No</th><th>Input</th><th>Output</th>";
    var tableBottom = "</table></form>";
    var insideArray = data[j];
        
    for(deviceTitle in insideArray){
    var fbdCaption = "<caption>" + deviceTitle + "</caption>\n";
    console.log(deviceTitle);

      for(k=0; k<insideArray[deviceTitle]["input"].length; k++){
      var fdbCellData = "<tr><td>" + (k+1) + "</td>" + "<td>" + insideArray[deviceTitle]["input"][k] + "</td>" + "<td>" + insideArray[deviceTitle]["output"][k] + "</td></tr>\n";
      console.log(insideArray[deviceTitle]["input"][k]);
      console.log(insideArray[deviceTitle]["output"][k]);
      }
    }
    document.getElementById('container').innerHTML = tableTop + fbdCaption + tableHeader + fdbCellData + tableBottom;
  }
}
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>title</title>
  </head>
  <body onload="tablesFromDb();">
    
    <div id="container"></div>

  <script src=js.js></script>
  </body>
</html>

UPDATE: I have it working partially, but I'm still having trouble understanding how this loop actually works. How to get the last for loop to iterate through (what I guess is) the above loop to display the correct contents of both tables.... I'm not very good at this....

var data = [
  {
    deviceOne: {
      input: ["oneInOne", "oneInTwo", "oneInThree", "oneInFour"],
      output: ["oneOutOne", "oneOutTwo", "oneOutThree"]
    }
  },
  {
    deviceTwo: {
      input: ["twoInOne", "twoInTwo", "twoInThree", "twoInFour"],
      output: ["twoOutOne", "twoOutTwo", "twoOutThree", "twoOutFour"]
    }
  }
];

    //var fdbCellData = "";
function tablesFromDb() {
  var tableTop = "";
  var tableBottom = "";
  var fdbCellData = "";
  
  for (j = 0; j < data.length; j++) {
    var insideArray = data[j];
    //var fdbCellData = "";

    for(var deviceTitle in insideArray){
    tableTop += "<form><table border=1><caption>" + deviceTitle + "</caption>";
    tableTop += "<tr><th>No</th><th>Input</th><th>Output</th>";
    tableBottom += "</table></form>";
    console.log(deviceTitle);
    //var fdbCellData = "";
  
    for (k = 0; k < insideArray[deviceTitle].input.length; k++) {
      fdbCellData += "<tr><td>" + (k + 1) + "</td>";
      fdbCellData += "<td>" + insideArray[deviceTitle].input[k] + "</td>";
      fdbCellData += "<td>" + insideArray[deviceTitle].output[k] + "</td></tr>";
    }
    }

  }
  document.getElementById("container").innerHTML =
    tableTop + fdbCellData + tableBottom;
}
<body onload="tablesFromDb();">
    
    <div id="container"></div>

  </body>

2
  • it looks like fbdCaption gets reassigned in your for loop Commented Dec 10, 2018 at 21:12
  • thanks @AndrewKim This helped me get it partially working... Commented Dec 12, 2018 at 1:57

3 Answers 3

1

You need to declare fbdCaption outside of your loop, and accumulate values to it inside the loop. In your second attempt there is still an issue:

The HTML for both table "tops" are concatenated in a dedicatedvariable and then output like that, which means you get the two tops right after each other in the output without the data rows below the first one. Similar things happen with the other two variables that collect HTML. It also means the output HTML structure is in fact invalid.

It is not that hard to fix that, but I prefer another way to build HTML elements: using DOM methods.

Also, you have one case where you have more output values than input values. If it would be the other way, your output would be incomplete.

Finally you use some iteration variables without defining them explicitly. This makes them global.

Working code could look like this:

// A helper function to append one table-row containing the given texts (array)
function insertRowWithTexts(table, tag, texts) {
    const row = table.insertRow();
    for (const text of texts) {
        const elem = document.createElement(tag); // Either a TD or a TH
        elem.textContent = text === undefined ? "" : text;
        row.appendChild(elem);
    }
}

function tablesFromDb(data) {
    for (const obj of data) {
        for (const deviceTitle in obj) {
            const { input, output } = obj[deviceTitle];
            const table = document.createElement("table");
            table.createCaption().textContent = deviceTitle;
            insertRowWithTexts(table, "th", ["No", "Input", "Output"]);
            for (let k = 0; k < Math.max(input.length, output.length); k++) {
                insertRowWithTexts(table, "td", [k+1, input[k], output[k]]);
            }
            document.getElementById("container").appendChild(table);
        }
    }
}

var data = [{deviceOne: {input: ["oneInOne", "oneInTwo", "oneInThree", "oneInFour"], output: ["oneOutOne", "oneOutTwo", "oneOutThree"]}},{deviceTwo: {input: ["twoInOne", "twoInTwo", "twoInThree", "twoInFour"],output: ["twoOutOne", "twoOutTwo", "twoOutThree", "twoOutFour"]}}];

document.addEventListener('DOMContentLoaded', () => tablesFromDb(data));
td, th {
    border: 1px solid;
}
<div id="container"></div>

The advantage in using textContent = on HTML Element objects, is that it takes care of any character escaping that might be needed. For instance, if a text contains volt&ampere it will be properly escaped so it also renders like that, and not like "volt&ere" or something else.

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

2 Comments

thanks @trincot I worked on this all day yesterday, and have only managed to get both tables with the correct caption, however only only the last table displays as complete...
Ahhhhh, you know, my next attempt I was going to try the createElement method. More importantly, I thought the problem was with the loop and would need [somehow] to use another function in there somewhere. Thanks so much for taking the time to answer, I'm going to try this today....
0

Need to define your cell data outside your loop. Try this:

function tablesFromDb(){
    for(j=0; j<data.length; j++){
        var tableTop = "<form><table>";
        var tableHeader = "<tr><th>No</th><th>Input</th><th>Output</th>";
        var tableBottom = "</table></form>";
        var insideArray = data[j];
        var fbdCaption = "<caption>" + deviceTitle + "</caption>\n";
        var fdbCellData = "";
        for(deviceTitle in insideArray){
           for(k=0; k<insideArray[deviceTitle]["input"].length; k++){
              fdbCellData += "<tr><td>" + (k+1) + "</td>" + "<td>" + insideArray[deviceTitle]["input"][k] + "</td>" + "<td>" + insideArray[deviceTitle]["output"][k] + "</td></tr>\n";
           }
        }
        document.getElementById('container').innerHTML = tableTop + fbdCaption + tableHeader + fdbCellData + tableBottom;
      }
    }

1 Comment

Thanks @Ben worked on this all day yesterday and have only managed to get it partially working.
0

FINALLY IT WORKS!! Thanks to @trincot and my son for pointing me in the right direction... . For those interested, I changed the data structure a little, to make it more manageable. The rest you can see in the code.

const data = [
  {
    name: "deviceOne",
    input: ["oneInOne", "oneInTwo", "oneInThree", "oneInFour"],
    output: ["oneOutOne", "oneOutTwo", "oneOutThree"]
  },
  {
    name: "deviceTwo",
    input: ["twoInOne", "twoInTwo", "twoInThree", "twoInFour"],
    output: ["twoOutOne", "twoOutTwo", "twoOutThree", "twoOutFour"]
  },
    {
    name: "deviceThree",
    input: ["threeInOne", "threeInTwo", "threeInThree", "threeInFour"],
    output: ["threeOutOne", "threeOutTwo", "threeOutThree", "threeOutFour"]
  }
];


const container = document.getElementById('container');

for (var i = 0;  i < data.length; i++) {

let title = document.createElement('caption');
let table = document.createElement('table');
table.setAttribute('border', 1);
  var row = table.insertRow(0);
  var cell1 = row.insertCell(0);
  var cell2 = row.insertCell(1);
  var cell3 = row.insertCell(2);
  cell1.innerHTML = 'No';
  cell2.innerHTML = 'Input';
  cell3.innerHTML = 'Output';
    
	for (var j = 0; j < data[i].input.length; j++) {
  	var dataRow = table.insertRow();
    var dataCell1 = dataRow.insertCell();
    var dataCell2 = dataRow.insertCell();
    var dataCell3 = dataRow.insertCell();
    dataCell1.innerHTML = j+1;
    dataCell2.innerHTML = data[i].input[j]
    dataCell3.innerHTML = data[i].output[j]

  }
  
  title.innerText = data[i].name;
  
  container.appendChild(title);
  container.appendChild(table);

}
<div id="container">

</div>

Comments

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.