skip to Main Content

I’m trying to fill an element on a website with data from a JSON object. For formatting I try to use a html table.

This is the javascript code:

teams = {
    "1": {
        "channels": {
            "1_1": {
                "displayName": "General",
                "description": "Systeembeheer cq ICT Service groep"
            },
            "1_2": {
                "description": "Hier staan de tabbladen van het Ticketsysteem",
                "displayName": "TicketSysteem"
            }
        },
        "displayName": "ASC Systeembeheer",
        "description": "Systeembeheer cq ICT Service groep"
    },
    "2": {
        "channels": {
            "2_1": {
                "description": "Handleidingen",
                "displayName": "Handleidingen"
            },
            "2_2": {
                "description": null,
                "displayName": "Externe toegang"
            }
        }
    }
}

var list = document.querySelector('#list');
list.innerHTML = '<table>';
for (let id in teams){
  list.innerHTML += `<tr><td>${id}</td></tr>`;
}
list.innerHTML += '</table>'

It does place a table open and close tag, but it has no content.
The content is placed after the table close tag without the tr or td tags.

I’m kinda flabbergasted about this. I was expecting a table, a simple one but at least one I could build on.

teams = {
  "1": {
    "channels": {
      "1_1": {
        "displayName": "General",
        "description": "Systeembeheer cq ICT Service groep"
      },
      "1_2": {
        "description": "Hier staan de tabbladen van het Ticketsysteem",
        "displayName": "TicketSysteem"
      }
    },
    "displayName": "ASC Systeembeheer",
    "description": "Systeembeheer cq ICT Service groep"
  },
  "2": {
    "channels": {
      "2_1": {
        "description": "Handleidingen",
        "displayName": "Handleidingen"
      },
      "2_2": {
        "description": null,
        "displayName": "Externe toegang"
      }
    }
  }
}

var list = document.querySelector('#list');
list.innerHTML = '<table>';
for (let id in teams) {
  list.innerHTML += `<tr><td>${id}</td></tr>`;
}
list.innerHTML += '</table>'
<div id="list">
  <p>blaat</p>
</div>

What is going on? What don’t I get
I’ve got a codepen set up: https://codepen.io/peter-kaagman/pen/ExOmwgW

5

Answers


  1. You need to assign innerHTML at once.
    When you do list.innerHTML = '<table>' you are actually adding self-closed <table>:

    enter image description here

    Then you try to add table rows which added as text because you add them outside a table.

    So finally:

    NEVER DO innerHTML += ‘any html’ because it’s equivalent to:

    const currentHTML = elem.innerHTML;
    elem.innerHTML = ''; // to make clear it's emptied
    elem.innerHTML = currentHTML + newHTML:
    
    

    Actually every time you do that you overwrite previously added DOM elements. Folks have a lot of problems with this pattern puzzling why DOM is broken or event listeners are removed.
    Also layout changes happen making the things more worse and slower…

    teams = {
        "1": {
            "channels": {
                "1_1": {
                    "displayName": "General",
                    "description": "Systeembeheer cq ICT Service groep"
                },
                "1_2": {
                    "description": "Hier staan de tabbladen van het Ticketsysteem",
                    "displayName": "TicketSysteem"
                }
            },
            "displayName": "ASC Systeembeheer",
            "description": "Systeembeheer cq ICT Service groep"
        },
        "2": {
            "channels": {
                "2_1": {
                    "description": "Handleidingen",
                    "displayName": "Handleidingen"
                },
                "2_2": {
                    "description": null,
                    "displayName": "Externe toegang"
                }
            }
        }
    }
    
    var list = document.querySelector('#list');
    list.innerHTML = '<table>' + Object.keys(teams).map(id => `<tr><td>${id}</td></tr>`).join('') + '</table>';
    <div id="list">
      <p>blaat</p>
    </div>
    Login or Signup to reply.
  2. The problem is because you need to set innerHTML to a complete valid HTML string. You cannot append part of a HTML element in one operation, then add content in another, then close the tag again.

    To fix the problem concatenate the HTML in to a string variable, then set innerHTML once, when that HTML is complete:

    teams = {
      "1": {
        "channels": {
          "1_1": {
            "displayName": "General",
            "description": "Systeembeheer cq ICT Service groep"
          },
          "1_2": {
            "description": "Hier staan de tabbladen van het Ticketsysteem",
            "displayName": "TicketSysteem"
          }
        },
        "displayName": "ASC Systeembeheer",
        "description": "Systeembeheer cq ICT Service groep"
      },
      "2": {
        "channels": {
          "2_1": {
            "description": "Handleidingen",
            "displayName": "Handleidingen"
          },
          "2_2": {
            "description": null,
            "displayName": "Externe toegang"
          }
        }
      }
    }
    
    var list = document.querySelector('#list');
    let html = '<table>';
    for (let id in teams) {
      html += `<tr><td>${id}</td></tr>`;
    }
    html += '</table>';
    list.innerHTML = html;
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <div id="list"></div>
    Login or Signup to reply.
  3. Every time you modify innerHTML you modify the DOM and the browser normalises it. You are not modifying the HTML source code.


    list.innerHTML = '<table>';
    

    Here you create a table element. The missing </table> is added by the browser’s error recovery.


    list.innerHTML += `<tr><td>${id}</td></tr>`;
    

    Not you append a <tr> element to the contents of the node.

    So the contents you are trying to create are:

    <table></table>
    <tr><td>${id}</td></tr>
    

    … which doesn’t make sense.


    If you are going to use innerHTML then build a string with the complete value you want to assign, then assign it to innerHTML in one go.

    let table = '<table>';
    for (let id in teams){
      table += `<tr><td>${id}</td></tr>`;
    }
    table += '</table>';
    list.innerHTML = table;
    
    Login or Signup to reply.
  4. You can populate an HTML table with data from a JSON object by iterating over the object and dynamically creating table rows and cells using JavaScript. Here’s an example solution:

    teams = {
        "1": {
            "channels": {
                "1_1": {
                    "displayName": "General",
                    "description": "Systeembeheer cq ICT Service groep"
                },
                "1_2": {
                    "description": "Hier staan de tabbladen van het Ticketsysteem",
                    "displayName": "TicketSysteem"
                }
            },
            "displayName": "ASC Systeembeheer",
            "description": "Systeembeheer cq ICT Service groep"
        },
        "2": {
            "channels": {
                "2_1": {
                    "description": "Handleidingen",
                    "displayName": "Handleidingen"
                },
                "2_2": {
                    "description": null,
                    "displayName": "Externe toegang"
                }
            }
        }
    }
    
    var list = document.querySelector('#list');
    var table = document.createElement('table');
    
    for (let id in teams) {
      var team = teams[id];
    
      var row = document.createElement('tr');
    
      var idCell = document.createElement('td');
      idCell.textContent = id;
      row.appendChild(idCell);
    
      var displayNameCell = document.createElement('td');
      displayNameCell.textContent = team.displayName;
      row.appendChild(displayNameCell);
    
      var descriptionCell = document.createElement('td');
      descriptionCell.textContent = team.description;
      row.appendChild(descriptionCell);
    
      table.appendChild(row);
    
      if (team.channels) {
        for (let channelId in team.channels) {
          var channel = team.channels[channelId];
    
          var channelRow = document.createElement('tr');
    
          var channelIdCell = document.createElement('td');
          channelIdCell.textContent = channelId;
          channelRow.appendChild(channelIdCell);
    
          var channelDisplayNameCell = document.createElement('td');
          channelDisplayNameCell.textContent = channel.displayName;
          channelRow.appendChild(channelDisplayNameCell);
    
          var channelDescriptionCell = document.createElement('td');
          channelDescriptionCell.textContent = channel.description;
          channelRow.appendChild(channelDescriptionCell);
    
          table.appendChild(channelRow);
        }
      }
    }
    
    list.appendChild(table);
    <div id="list">
      <p>blaat</p>
    </div>

    In this code, we iterate over the teams object and dynamically create table rows () and cells () for each team and channel. We set the appropriate text content for each cell and append them to the table. Finally, we append the table to an HTML element with the id attribute set to "list" (adjust this ID according to your HTML structure).

    By using the DOM API to create and append the table elements, we ensure that the table structure is correctly maintained and the data is populated within the appropriate cells.

    Hope this helps! Let me know if you have any further questions.

    Login or Signup to reply.
  5. Do not use innerHTML. Use the available document methods].

    Here is an example for your code.

    const teamsObj = {
      "1": {
        "channels": {
          "1_1": {
            "displayName": "General",
            "description": "Systeembeheer cq ICT Service groep"
          },
          "1_2": {
            "description": "Hier staan de tabbladen van het Ticketsysteem",
            "displayName": "TicketSysteem"
          }
        },
        "displayName": "ASC Systeembeheer",
        "description": "Systeembeheer cq ICT Service groep"
      },
      "2": {
        "channels": {
          "2_1": {
            "description": "Handleidingen",
            "displayName": "Handleidingen"
          },
          "2_2": {
            "description": null,
            "displayName": "Externe toegang"
          }
        }
      }
    }
    
    const list = document.querySelector('#list');
    const table = document.createElement(`table`);
    const aRow = document.createElement(`tr`);
    const aCell = document.createElement(`td`);
    const rows = Object.entries(teamsObj).forEach( ([id, ]) => {
      // create a new row by cloning [aRow]
      const row = aRow.cloneNode();
      // create a new table cell by cloning [aCell]
      const cell = aCell.cloneNode();
      // fill the cell with the id
      cell.textContent = id;
      // append the cell to the row
      row.append(cell);
      // append the row to the table
      table.append(row);
    });
    
    // the table now only exists in memory
    // so append it to div#list to add it to
    // the document.
    list.append(table);
    <div id="list">
      <p>blaat</p>
    </div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search