Enrique GF
Enrique GF

Reputation: 1295

Looping over an array of objects on Vuejs template

I have the following JSON:

{
  "games": [
    {
      "id": 1,
      "init_date": "2020-02-11T07:47:33.627+0000",
      "players_in_game": [
        {
          "id": 1,
          "player": {
            "id": 1,
            "player": "Jack Bauer",
            "email": "[email protected]"
          }
        },
        {
          "id": 2,
          "player": {
            "id": 2,
            "player": "Chloe O'Brian",
            "email": "[email protected]"
          }
        }
      ]
    },
    {
      "id": 2,
      "init_date": "2020-02-11T08:47:33.627+0000",
      "players_in_game": [
        {
          "id": 3,
          "player": {
            "id": 1,
            "player": "Rome Jones",
            "email": "[email protected]"
          }
        },
        {
          "id": 4,
          "player": {
            "id": 2,
            "player": "Ludacris",
            "email": "[email protected]"
          }
        }
      ]
    },
  ]
}  

And for every 'players-in game' I want to show one Player VS the other, let's say:

**PLayer 1   VS    PLayer 2**
Jack Bauer         Chloe O'Brian
Rome Jones         Ludacris

But can't find the way of doing it properly. Here the code I put:

<tr v-for="(general, index) in getGamesAll.games" v-bind:key="index">
  <td>Game {{general.id}}</td>
  <td v-for="(gamePlayer, j) in general" :key="j">

    {{general.players_in_game.player.player}}
  </td>
  <td>vs</td>
   <td v-for="(gamePlayer, j) in general" :key="j">
     {{general.players_in_game.player.player}}
  </td>
</tr>

I already know this is wrong, because I'm looping over the same players-in_game reaching to player, but neither of both cases specify which player are inside the object I'm talking about. How could this be accomplished?

Upvotes: 0

Views: 87

Answers (2)

Leandro Matilla
Leandro Matilla

Reputation: 1011

You just can find the players by id like this:

function getPlayers(games, playerNumber) {

    const players = games.map(game => { // for each game
        return game.players_in_game.map(players => { // for each player
            if (players.player.id === playerNumber) {
                return players.player;
            }
        }).filter(player => player); // Remove distinct players
    });

    return players; // Return players with id === playerNumber
}
getPlayers(data.games, 2);

Return should be:

enter image description here

Then your template...

<tr v-for="(general, index) in getGamesAll.games" v-bind:key="index">
  <td>Game {{general.id}}</td>

  <td v-for="firstPlayer in getPlayers(getGamesAll.games, 1)">
    {{ firstPlayer.player }}
  </td>

  <td>VS</td>

   <td v-for="secondPlayer in getPlayers(getGamesAll.games, 2)">
    {{ secondPlayer.player }}
  </td>
</tr>

Upvotes: 0

Kyle
Kyle

Reputation: 1503

The main thing was to target the correct node when looping.

In the example, 'general' represents one of the items in 'getGamesAll'.

Once we are in that instance of 'general' we want to do our second loop off of the array at node 'players_in_game'.

Then, instead of looping over the same object twice to represent each row, we would try and figure a way to do it with a single loop. In the snippet, I'm just using the single td element and conditionally adding in that 'vs' message.

var getGamesAll = {
  "games": [
    {
      "id": 1,
      "init_date": "2020-02-11T07:47:33.627+0000",
      "players_in_game": [
        {
          "id": 1,
          "player": {
            "id": 1,
            "player": "Jack Bauer",
            "email": "[email protected]"
          }
        },
        {
          "id": 2,
          "player": {
            "id": 2,
            "player": "Chloe O'Brian",
            "email": "[email protected]"
          }
        }
      ]
    },
    {
      "id": 2,
      "init_date": "2020-02-11T08:47:33.627+0000",
      "players_in_game": [
        {
          "id": 3,
          "player": {
            "id": 1,
            "player": "Rome Jones",
            "email": "[email protected]"
          }
        },
        {
          "id": 4,
          "player": {
            "id": 2,
            "player": "Ludacris",
            "email": "[email protected]"
          }
        }
      ]
    },
  ]
}

new Vue({
el:"#players",
data:{
  getGamesAll: getGamesAll
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>

<table id="players">
<tr v-for="(general, index) in getGamesAll.games" v-bind:key="index">
  <td>Game {{general.id}}:</td>
  <td v-for="(gamePlayer, j) in general.players_in_game" :key="j">
    {{gamePlayer.player.player}} <span v-if="j<1">vs</span>
  </td>
</tr>
</table>

Upvotes: 1

Related Questions