Home > other >  How do I loop through a nested object and subsequently add the values to HTML table cells, in Javasc
How do I loop through a nested object and subsequently add the values to HTML table cells, in Javasc

Time:10-09

I would like to insert parsed JSON data into a HTML table via Javascript. I think I am close to a solution, but can't figure out the final step.

Goal: I need to insert the name, age, secretIdentity and powers of three superheroes into their respective columns in a table. The data comes from a JSON file. I parsed it and it is ready to use in Javascript. I want to loop through the objects within the data and insert the correct data in the cells. I am not allowed to use jQuery or similar techniques.

Problem: The problem is that I can not seem to loop through the objects (name, age etc) for each superhero and add it to the cell. How do I target/reference the objects for use in a loop? For example, this 'works', but gives the wrong result since I don't want to loop through the names:

JavaScript code:

for(i = 0; i < members.length; i  ) {
        function addRow(tableID) {
        let tableRef = document.getElementById(tableID);
        let newRow = tableRef.insertRow(-1);

        for(x = 0; x < 4; x  ) {
        let newCell = newRow.insertCell(0);
        let newText = document.createTextNode(members[i].name);
        newCell.appendChild(newText);
        }

enter image description here

Instead, I want to loop through the object like this, in a horizontal way.

enter image description here

Expected solution: I expect the solution to look something like this, but it doesn't work:

for(x = 0; x < 4; x  ) {
        let newCell = newRow.insertCell(0);
        let newText = document.createTextNode(members[i].obj[x]);
        newCell.appendChild(newText);

JSON data:

const data = 
  [ { squadName  : 'Super Hero Squad'
    , homeTown   : 'Metro City'
    , formed     : 2016
    , secretBase : 'Super tower'
    , active     : true
    , members : 
      [ { name           : 'Molecule Man'
        , age            : 29
        , secretIdentity : 'Dan Jukes'
        , powers         : 
          [ 'Radiation resistance'
          , 'Turning tiny'
          , 'Radiation blast'
        ] } 
      , { name           : 'Madame Uppercut'
        , age            : 39
        , secretIdentity : 'Jane Wilson'
        , powers         : 
          [ 'Million tonne punch'
          , 'Damage resistance'
          , 'Superhuman reflexes'
    ] } ] } 
  //, {}
  ]      

Is there anyone that is able to help out? Thanks in advance!

CodePudding user response:

Just loop through each property of object member[i]

for (i = 0; i < members.length; i  ) {
    addRow('table', members[i]);
}

function addRow(tableID, member) {
    let tableRef = document.getElementById(tableID);
    let newRow = tableRef.insertRow(-1);
    for (let prop in member) {
        let newCell = newRow.insertCell(-1);
        let newText = document.createTextNode(member[prop]);
        newCell.appendChild(newText);
    }
}

CodePudding user response:

I'm not 100% sure about what columns you need but, I think this is close what you wanted. Hopefully you can see the general pattern to creating a DOM element, filling it with data and appending it to the table.

const data = 
  [ { squadName  : 'Super Hero Squad'
    , homeTown   : 'Metro City'
    , formed     : 2016
    , secretBase : 'Super tower'
    , active     : true
    , members : 
      [ { name           : 'Molecule Man'
        , age            : 29
        , secretIdentity : 'Dan Jukes'
        , powers         : 
          [ 'Radiation resistance'
          , 'Turning tiny'
          , 'Radiation blast'
        ] } 
      , { name           : 'Madame Uppercut'
        , age            : 39
        , secretIdentity : 'Jane Wilson'
        , powers         : 
          [ 'Million tonne punch'
          , 'Damage resistance'
          , 'Superhuman reflexes'
    ] } ] } 
  //, {}
  ]
  
const table = document.getElementById('root');

data.forEach(squad => {
  squad.members.forEach(hero => {
    const tr = document.createElement("tr")
    const nameTd = document.createElement("td")
    nameTd.append(hero.name)
    const ageTd = document.createElement("td")
    ageTd.append(hero.age)
    const secretTd = document.createElement("td")
    secretTd.append(hero.secretIdentity)
    const powersTd = document.createElement("td")
    powersTd.append(hero.powers.join(', '))
    
    tr.append(nameTd)
    tr.append(ageTd)
    tr.append(secretTd)
    tr.append(powersTd)
    
    table.append(tr)
  })
})
td {
  border: solid black 1px;
}
<table id="root">

</table>

CodePudding user response:

What you are looking for in the nested loop, the horizontal one, is "for in". "for in" will loop through the properties of an Object. Refer to this article

https://www.w3schools.com/js/js_loop_forin.asp

But, I do not recommend you to use this method - simply access key value to generate each collumn (<td>), because the order of keys is not guaranteed in a loop. You still have to check the key in the nested loop to make it safe.

Does JavaScript guarantee object property order?

CodePudding user response:

you can do that:

const data = 
  [ { squadName  : 'Super Hero Squad'
    , homeTown   : 'Metro City'
    , formed     : 2016
    , secretBase : 'Super tower'
    , active     : true
    , members : 
      [ { name           : 'Molecule Man'
        , age            : 29
        , secretIdentity : 'Dan Jukes'
        , powers         : 
          [ 'Radiation resistance'
          , 'Turning tiny'
          , 'Radiation blast'
          ] } 
      , { name           : 'Madame Uppercut'
        , age            : 39
        , secretIdentity : 'Jane Wilson'
        , powers         : 
          [ 'Million tonne punch'
          , 'Damage resistance'
          , 'Superhuman reflexes'
          ] } 
      , { name           : 'Eternal Flame'
        , age            : 1000000
        , secretIdentity : 'Unknow'
        , powers         : 
          [ 'night lighting'
    ] } ] } 
  //, {}
  ] 
const keys_0 = [ 'squadName', 'homeTown', 'formed', 'secretBase', 'active' ]
const keys_1 = [ 'name', 'age', 'secretIdentity', 'powers' ]

data.forEach(herosGroup=>
  {
  let 
    tabEl = document.createElement('table')
  , tHead = tabEl.createTHead()
  , tBody = tabEl.createTBody()
  , newRow = tHead.insertRow()
    ;
  tabEl.className = 'top'
  document.body.appendChild(tabEl)

  keys_0.forEach(prop=> newRow.insertCell().textContent = prop )
  newRow = tBody.insertRow()
  keys_0.forEach(prop=> newRow.insertCell().textContent = herosGroup[prop] )

  // 'name', 'age', 'secretIdentity', 'powers' trip...
  tabEl = document.createElement('table')
  tHead = tabEl.createTHead()
  tBody = tabEl.createTBody()
  newRow = tHead.insertRow()

  document.body.appendChild(tabEl)  

  keys_1.forEach(prop=> newRow.insertCell().textContent = prop )

  herosGroup.members.forEach(hero=>
    {
    newRow = tBody.insertRow()

    keys_1.forEach(prop=>
      {
      if (prop!='powers') newRow.insertCell().textContent = hero[prop]
      else                newRow.insertCell().innerHTML   = hero[prop].join('<br>') 
      })
    })
  })  // forEach(herosGroup=>
body {
  font-family : Arial, Helvetica, sans-serif;
  font-size   : 14px;
  }
table {
  border-collapse : collapse;
  margin          : .7em 1em;
  }
table.top {
  margin-top : 1em;
  }
td  {
  padding        : .2em .8em;
  border         : 1px solid darkblue;
  vertical-align : text-top;
  white-space    : nowrap;
  }
thead { 
  background-color: aquamarine;
  font-weight     : bold;
  }

  • Related