简体   繁体   中英

Fill HTML table with values from JS loop

I want my table 'scores' to be populated by the 'ability' values held in the object.

I believe my problems lie with the following lines:

var player = document.getElementById("player" + i + 1);
playerscore.innerText = playerList[i].ability;

I can get this to work by not using a value of 'i' to increment the ID's, I simply write a line of code for each ID. I'm sure this is not the best way of doing things and therefore want to cycle through the ID's using the loop already set up.

Where have I gone wrong with my code and what would be a better way of doing this?

Thanks in advance.

 var playerList = [ {name: "player1", highScore: 1, ability: 8}, {name: "player2", highScore: 1, ability: 7}, {name: "player3", highScore: 1, ability: 6}, {name: "player4", highScore: 1, ability: 5}, {name: "player5", highScore: 1, ability: 4}, {name: "player6", highScore: 1, ability: 3}, {name: "player7", highScore: 1, ability: 2}, {name: "player8", highScore: 1, ability: 1} ]; for (var i = 0; i < playerList.length; i++) { console.log(i); var player = document.getElementById("player" + i + 1); var playerscore = document.getElementById('player' + i + 1 + "score") var progress=Math.random(); progress=11*progress; progress=Math.floor(progress); playerList[i].ability=playerList[i].ability+progress; console.log(playerList[i]) //add players score to the table// playerscore.innerText = playerList[i].ability; } 
 <table> <tr> <th>Player</th> <th>Score</th> </tr> <tr> <td id="player1">1</td> <td id="player1score">0</td> </tr> <tr> <td id="player2">2</td> <td id="player2score">0</td> </tr> <tr> <td id="player3">3</td> <td id="player3score">0</td> </tr> <tr> <td id="player4">4</td> <td id="player4score">0</td> </tr> <tr> <td id="player5">5</td> <td id="player5score">0</td> </tr> <tr> <td id="player6">6</td> <td id="player6score">0</td> </tr> <tr> <td id="player7">7</td> <td id="player7score">0</td> </tr> <tr> <td id="player8">8</td> <td id="player8score">0</td> </tr> </table> 

Your initial problem was that you didn't de-reference your counting variable correctly, and so the maths where working out an incorrect index to use in the string concatenation.

To fix that, you need to place your "i + 1" expression into a set of normal brackets in your getElementById call.

Basically your initial call:

var player = document.getElementById("player" + i + 1);

Needs to become:

var player = document.getElementById("player" + (i + 1));

In the former version, the effect is that the final 1 gets turned into a string, and thus becomes part of the string, rather than an addition to the index as intended.

A much better way to do what your attempting in vanilla JS is to skip doing all this +1 stuff in the first place and make your code reusable.

If you format your table as per W3C recommendations, then you'll end up with something like the following:

<table id="myTable">
  <thead>
    <tr>
      <th>Player</th>
      <th>Score</th>
    </tr>
  </thead>
  <tbody id="myTableBody">
    <tr>
      <td>Player 1</td>
      <td>1</td>
    </tr>
    <tr>
      <td>Player 2</td>
      <td>2</td>
    </tr>
    <!-- More TR's here as needed -->
  </tbody>
</table>

Using thead and tbody mean that you can manipulate the header and body parts of your table separately of each other, allowing you to then use the underlying JS api and table properties, rather than having to perform the risky step of building strings and possibly getting that string incorrectly formatted.

I'm not saying that building strings is the wrong way to do it, but it's error prone, and as you've seen all it takes is a small calculation error, and you end up with an ID name that doesn't match anything.

Adding rows to your table under program control in JavaScript, is as simple as the following:

function addRow(playerName, playerScore)
{
  var tableBody = document.getElementById('myTableBody');
  var newRow = tableBody.insertRow(tableBody.rows.length);
  var nameCell = newRow.insertCell(0);
  var scoreCell = newRow.insertCell(1);
  var playerText = document.createTextNode(playerName);
  var scoreText = document.createTextNode(playerScore);
  nameCell.appendChild(playerText);
  scoreCell.appendChild(scoreText);
}

That will add the new row to the end of your table body.Removing a row by index is just as simple:

function removeRow(rowNumber)
{
  var tableBody = document.getElementById('myTableBody');
  tableBody.deleteRow(rowNumber);
}

An IMPORTANT thing to remember is that as soon as you delete a row, the rest will move up to take it's place. This means if you remove the first one (Row 0), then after that is done, 1 will become 0, 2 will become 1, 3 will become 2 and so on.

This means if you want to remove the top two, you'll need to remove index 0 twice, not 0 and 1 as you might think.

As for adding your data array into the table, well with the add function it now becomes as simple as:

playerList.forEach(function(listItem){
  addRow(listItem.name, listItem.ability)
});

and if you need to change the actual text data, it's a simple matter of the following:

function changePlayerName(rowNumber, playerName)
{
  var tableBody = document.getElementById('myTableBody');
  tableBody.Rows[rowNumber].cells[0].innerText = playerName;
}

function changePlayerScore(rowNumber, playerScore)
{
  var tableBody = document.getElementById('myTableBody');
  tableBody.Rows[rowNumber].cells[1].innerText = playerScore;
}

Doing things this way, keeps your code neat and easy to read and understand. When you come back to it in a month, you'll be able to still understand what you where trying to achieve, and it'll aid you in your learning.

There are a dozen other ways this could be done too. You could have placed ID's on all your tags as you have in your original version, then referenced those via string concatenation, the method you used, you could have used class selectors with row ID's to target an actual direct element, you could have used JQuery too.

However, if you are building complex UI's for what looks like a game, then I would strongly suggest looking at using a modern UI build system such as 'Aurelia' or 'Angular' , both of which use the newer JS2016/2017 syntax, allowing you to write really clean code, with easily understandable constructs like "for loops" , "repeat loops" and all the other nice features that modern JavaScript brings. Don't worry about backward comparability with the modern UI frameworks either, because most of them will build code that is compatible with older browsers.

While I'm a strong believer in using vanilla JavaScript as you are in this task, I'm also a believer in making the task easier if that possibility exists.

Wrap your i + 1 into paranthesis in your getElementById - see demo below:

 var playerList = [ {name: "player1", highScore: 1, ability: 8}, {name: "player2", highScore: 1, ability: 7}, {name: "player3", highScore: 1, ability: 6}, {name: "player4", highScore: 1, ability: 5}, {name: "player5", highScore: 1, ability: 4}, {name: "player6", highScore: 1, ability: 3}, {name: "player7", highScore: 1, ability: 2}, {name: "player8", highScore: 1, ability: 1} ]; for (var i = 0; i < playerList.length; i++) { var player = document.getElementById("player" + (i + 1)); var playerscore = document.getElementById('player' + (i + 1) + "score") var progress=Math.random(); progress=11*progress; progress=Math.floor(progress); playerList[i].ability=playerList[i].ability+progress; //add players score to the table// playerscore.innerText = playerList[i].ability; } 
 <table> <tr> <th>Player</th> <th>Score</th> </tr> <tr> <td id="player1">1</td> <td id="player1score">0</td> </tr> <tr> <td id="player2">2</td> <td id="player2score">0</td> </tr> <tr> <td id="player3">3</td> <td id="player3score">0</td> </tr> <tr> <td id="player4">4</td> <td id="player4score">0</td> </tr> <tr> <td id="player5">5</td> <td id="player5score">0</td> </tr> <tr> <td id="player6">6</td> <td id="player6score">0</td> </tr> <tr> <td id="player7">7</td> <td id="player7score">0</td> </tr> <tr> <td id="player8">8</td> <td id="player8score">0</td> </tr> </table> 

 var playerList = [ {name: "player1", highScore: 1, ability: 8}, {name: "player2", highScore: 1, ability: 7}, {name: "player3", highScore: 1, ability: 6}, {name: "player4", highScore: 1, ability: 5}, {name: "player5", highScore: 1, ability: 4}, {name: "player6", highScore: 1, ability: 3}, {name: "player7", highScore: 1, ability: 2}, {name: "player8", highScore: 1, ability: 1} ]; for (var i = 0; i < playerList.length; i++) { console.log(i); var player = document.getElementById("player" + (i + 1)); var playerscore = document.getElementById('player' + (i + 1) + "score") var progress=Math.random(); progress=11*progress; progress=Math.floor(progress); playerList[i].ability=playerList[i].ability+progress; console.log(playerList[i]) //add players score to the table// playerscore.innerText = playerList[i].ability; } 
 <table> <tr> <th>Player</th> <th>Score</th> </tr> <tr> <td id="player1">1</td> <td id="player1score">0</td> </tr> <tr> <td id="player2">2</td> <td id="player2score">0</td> </tr> <tr> <td id="player3">3</td> <td id="player3score">0</td> </tr> <tr> <td id="player4">4</td> <td id="player4score">0</td> </tr> <tr> <td id="player5">5</td> <td id="player5score">0</td> </tr> <tr> <td id="player6">6</td> <td id="player6score">0</td> </tr> <tr> <td id="player7">7</td> <td id="player7score">0</td> </tr> <tr> <td id="player8">8</td> <td id="player8score">0</td> </tr> </table> 

you have problem in concatenation , let say i=0, so this "player" + i + 1 = player01 so to get player1 use like this "player" + (i + 1) . this will evaluate brackets first then will concate with string.

The result of "player" + i + 1 will not be as expected. You can store i + 1 in a variable and use it in getElementById().

var index = i + 1;
var player = document.getElementById("player" + index);
var playerscore = document.getElementById('player' + index + "score")

Here is the working jsfiddle.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM