1

I'm trying to render data dynamically onto my HTML, and when selectPlayer is clicked the data it should show a drop down of player list and be able to select

Simultaneously when selected the stats should appear in <div id="stats"></div>

I can loop through the object but how do I present it dynamically onto the HTML?

<!DOCTYPE html>
<html lang="en">

<head>
  <link rel="stylesheet" href="./static/style.css" />
  <title>card</title>
</head>

<body>
  <header>
    <h1 id="selectPlayer">Select a player...</h1>
  </header>
  <div id="stats">
    <div id="name"></div>
    <div id="position"></div>
  </div>
  <script>
    const statsData = {
      players: [{
          player: {
            info: {
              positionInfo: "Defender"
            },
            name: {
              first: "Toby",
              last: "Alderweireld"
            },
            currentTeam: {
              name: "Tottenham Hotspur"
            }
          },
          stats: [{
              name: "goals",
              value: 5
            },
            {
              name: "losses",
              value: 20
            },
            {
              name: "wins",
              value: 48
            },
            {
              name: "draws",
              value: 23
            }
          ]
        },
        {
          player: {
            info: {
              positionInfo: "Midfielder"
            },
            name: {
              first: "Yaya",
              last: "Toure"
            },
            currentTeam: {
              name: "Manchester City"
            }
          },
          stats: [{
              name: "goals",
              value: 65
            },
            {
              name: "losses",
              value: 49
            },
            {
              name: "wins",
              value: 149
            },
            {
              name: "draws",
              value: 35
            }
          ]
        },
        {
          player: {
            info: {
              positionInfo: "Attacker"
            },
            name: {
              first: "Riyad",
              last: "Mahrez"
            },
            currentTeam: {
              name: "Leicester City"
            }
          },
          stats: [{
              name: "goals",
              value: 22
            },
            {
              name: "losses",
              value: 23
            },
            {
              name: "wins",
              value: 35
            },
            {
              name: "draws",
              value: 21
            }
          ]
        }
      ]
    };

    document.getElementById(
      "selectPlayer"
    ).innerHTML = `<h1>${statsData.players}<h1>`;
    document.getElementById(
      "stats"
    ).innerHTML = `<h2> ${statsData.player.stats}<h2>`;
  </script>
</body>

</html>

Appreciate quite a bit of code here but seem to be bit stuck

Heretic Monkey
  • 11,687
  • 7
  • 53
  • 122
Kingsamama
  • 33
  • 6
  • Looping is the key here, but we'll need to know how the output is going to look like to help out further. Look into [`Object.entries`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/entries) to create an iterable object and [`for...of`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of) to loop through the iterable object. – Emiel Zuurbier Feb 03 '20 at 20:16
  • There is no JSON involved here. JSON is a text format, and you just have JavaScript objects and arrays. – Heretic Monkey Feb 03 '20 at 20:18
  • Also, I've added a Stack Snippet around your code. Click Run code snippet and you'll see an error display. Do some research on that array. You might also look at some of the links in the Related column to the right of the question. For instance, [Loop through an array in JavaScript](https://stackoverflow.com/questions/3010840/loop-through-an-array-in-javascript?rq=1) and [How do I loop through or enumerate a JavaScript object?](https://stackoverflow.com/questions/684672/how-do-i-loop-through-or-enumerate-a-javascript-object?rq=1) – Heretic Monkey Feb 03 '20 at 20:22

2 Answers2

1

There are many ways this can be approached - a simple soltion would be to serialize the JSON to a string, and display that in your document directly using the JSON.stringify() method:

document.getElementById("stats").innerText = JSON.stringify(statsData.players);

const statsData = {
  players: [{
      player: {
        info: {
          positionInfo: "Defender"
        },
        name: {
          first: "Toby",
          last: "Alderweireld"
        },
        currentTeam: {
          name: "Tottenham Hotspur"
        }
      },
      stats: [{
          name: "goals",
          value: 5
        },
        {
          name: "losses",
          value: 20
        },
        {
          name: "wins",
          value: 48
        },
        {
          name: "draws",
          value: 23
        }
      ]
    },
    {
      player: {
        info: {
          positionInfo: "Midfielder"
        },
        name: {
          first: "Yaya",
          last: "Toure"
        },
        currentTeam: {
          name: "Manchester City"
        }
      },
      stats: [{
          name: "goals",
          value: 65
        },
        {
          name: "losses",
          value: 49
        },
        {
          name: "wins",
          value: 149
        },
        {
          name: "draws",
          value: 35
        }
      ]
    },
    {
      player: {
        info: {
          positionInfo: "Attacker"
        },
        name: {
          first: "Riyad",
          last: "Mahrez"
        },
        currentTeam: {
          name: "Leicester City"
        }
      },
      stats: [{
          name: "goals",
          value: 22
        },
        {
          name: "losses",
          value: 23
        },
        {
          name: "wins",
          value: 35
        },
        {
          name: "draws",
          value: 21
        }
      ]
    }
  ]
};

document.getElementById("stats").innerText = JSON.stringify(statsData.players);
<header>
  <h1 id="selectPlayer">Select a player...</h1>
</header>
<div id="stats"></div>

A better approach though, would be to present the JSON data in a way that is more readable. To do this, you'll typically need to "loop" over the collection (array) of data where, for each item of the array, you do some extra processing to make the data more readable.

You could for instance do something like the following to display the JSON data in an HTML table:

/* Assuming you've replaced the stats element with a table */
const table = document.getElementById("stats");

/* Loop through each item of statsData object */
statsData.players.forEach(item => {

  /* Extract info and name objects from player (optional) */
  const { info, name } = item.player;

  /* Add row to table for current player */
  const row = table.insertRow();

  /* Add cell for name/position to row */
  const cellName = row.insertCell(0);
  const cellPosition = row.insertCell(1);

  /* Fill each cell with data from current player data */
  cellName.innerText = name.first;
  cellPosition.innerText = info.positionInfo;
});

For a full working sample, see the code snippet below:

const statsData = {
  players: [{
      player: {
        info: {
          positionInfo: "Defender"
        },
        name: {
          first: "Toby",
          last: "Alderweireld"
        },
        currentTeam: {
          name: "Tottenham Hotspur"
        }
      },
      stats: [{
          name: "goals",
          value: 5
        },
        {
          name: "losses",
          value: 20
        },
        {
          name: "wins",
          value: 48
        },
        {
          name: "draws",
          value: 23
        }
      ]
    },
    {
      player: {
        info: {
          positionInfo: "Midfielder"
        },
        name: {
          first: "Yaya",
          last: "Toure"
        },
        currentTeam: {
          name: "Manchester City"
        }
      },
      stats: [{
          name: "goals",
          value: 65
        },
        {
          name: "losses",
          value: 49
        },
        {
          name: "wins",
          value: 149
        },
        {
          name: "draws",
          value: 35
        }
      ]
    },
    {
      player: {
        info: {
          positionInfo: "Attacker"
        },
        name: {
          first: "Riyad",
          last: "Mahrez"
        },
        currentTeam: {
          name: "Leicester City"
        }
      },
      stats: [{
          name: "goals",
          value: 22
        },
        {
          name: "losses",
          value: 23
        },
        {
          name: "wins",
          value: 35
        },
        {
          name: "draws",
          value: 21
        }
      ]
    }
  ]
};

const table = document.getElementById("stats");

/* Loop through each player of statsData object */
statsData.players.forEach(item => {

  /* Extract info and name objects from player (optional) */
  const { info, name } = item.player;
  
  /* Add row to table for current player */
  const row = table.insertRow();
  
  /* Add cell for name/position to row */
  const cellName = row.insertCell(0);
  const cellPosition = row.insertCell(1);
  
  /* Fill each cell with data from current player data */
  cellName.innerText = name.first;
  cellPosition.innerText = info.positionInfo;
});
<header>
  <h1 id="selectPlayer">Select a player...</h1>
</header>
<table id="stats">
  <thead><td>Name</td><td>Position</td></thead>
</table>

Hope that helps!

Dacre Denny
  • 29,664
  • 5
  • 45
  • 65
0

Since you want to be able to select a player, use a <select> element. Output the available players inside that select element. You can do that by creating an <option> element per player and adding it to the select element.

// Loop over each player in the array and use the player and info keys of each player.
for (const [ index, { player, stats } ] of statsData.players.entries()) {

  // Get the name and info of each player.
  const { name, info } = player;

  // Get the first and last name out of the name property.
  const { first, last } = name;

  // Get the position info out of the info property.
  const { positionInfo } = info;

  // Create an option element with the player info available and add it to the select element.
  // The index is the number of position in the players array.
  const html = `<option value="${index}">${first} ${last}</option>`;
  select.insertAdjacentHTML('beforeend', html);
}

Now the players are selectable in the list. And if you would add another player to the object with your player data, it would also appear in the list on page load.

Check out the snippet below to see this in action.

const statsData = {
  players: [{
      player: {
        info: {
          positionInfo: "Defender"
        },
        name: {
          first: "Toby",
          last: "Alderweireld"
        },
        currentTeam: {
          name: "Tottenham Hotspur"
        }
      },
      stats: [{
          name: "goals",
          value: 5
        },
        {
          name: "losses",
          value: 20
        },
        {
          name: "wins",
          value: 48
        },
        {
          name: "draws",
          value: 23
        }
      ]
    },
    {
      player: {
        info: {
          positionInfo: "Midfielder"
        },
        name: {
          first: "Yaya",
          last: "Toure"
        },
        currentTeam: {
          name: "Manchester City"
        }
      },
      stats: [{
          name: "goals",
          value: 65
        },
        {
          name: "losses",
          value: 49
        },
        {
          name: "wins",
          value: 149
        },
        {
          name: "draws",
          value: 35
        }
      ]
    },
    {
      player: {
        info: {
          positionInfo: "Attacker"
        },
        name: {
          first: "Riyad",
          last: "Mahrez"
        },
        currentTeam: {
          name: "Leicester City"
        }
      },
      stats: [{
          name: "goals",
          value: 22
        },
        {
          name: "losses",
          value: 23
        },
        {
          name: "wins",
          value: 35
        },
        {
          name: "draws",
          value: 21
        }
      ]
    }
  ]
};

const select = document.getElementById('select-player');
const nameField = document.getElementById('name');
const positionField = document.getElementById('position');
const statsList = document.getElementById('stats');

for (const [ index, { player, stats } ] of statsData.players.entries()) {
  const { name } = player;
  const { first, last } = name;
  const html = `<option value="${index}">${first} ${last}</option>`;
  select.insertAdjacentHTML('beforeend', html);
}

function emptyStatsList() {
  while(statsList.firstElementChild) {
    statsList.removeChild(statsList.firstElementChild);
  }
}

select.addEventListener('change', function(event) {
  const { target } = event;
  const { value } = target;
  const { player, stats } = statsData.players[value];
  const { name } = player;
  const { first, last } = name;
  nameField.innerText = `${first} ${last}`;
  positionField.innerText = value;
  // Empty stats list.
  emptyStatsList();
  // Loop through the stats array.
  for (const { name, value } of stats) {
    const stat = `<li>${name}: ${value}</li>`;
    statsList.insertAdjacentHTML('beforeend', stat);
  }
});
<select id="select-player">
  <option selected hidden value="">Select a player...</option>
</select>

<div>
  <div id="name"></div>
  <div id="position"></div>
  <ul id="stats"></ul>
</div>
Emiel Zuurbier
  • 19,095
  • 3
  • 17
  • 32
  • Epic work mate, thanks really helpful and good to see how you've put it together, now if I want to add the stats values to render once player is selected, I can add it to the event listener? – Kingsamama Feb 03 '20 at 22:09
  • Sure. I've modified the code to use the `index` of a player in the players array to select the proper player object when selecting a player in the select element. Now you can access all the data of your player in the event listener. The `stats` value is an array, so be sure to loop through it while outputting it. – Emiel Zuurbier Feb 03 '20 at 22:35
  • Cheers, im trying to tackle this now. I have added a new HTML ID 'Appearances', and now trying to add even listener for stats. Do I write my loop in the event listener? I can see its already looping through the statsData object? – Kingsamama Feb 05 '20 at 19:38
  • It is only looping through the `statsData` to add each player to the ` – Emiel Zuurbier Feb 05 '20 at 19:47
  • So the for loop will be similar to the above on looping through stats data and instead of adding player it will add the stats. This is my loop inside the EventsListener but its giving me an error that name of stats is undefined. – Kingsamama Feb 06 '20 at 11:28
  • for (const { stats } of statsData.players.entries()) { const { name, value } = stats; const htmlStat= `

    ${name} ${value}

    `; select.insertAdjacentHTML("beforeend", htmlStat); }
    – Kingsamama Feb 06 '20 at 11:28
  • I've made an error accessing stats. The example above is now corrected and working with the extra loop. – Emiel Zuurbier Feb 06 '20 at 13:57