Reputation: 35
This was resolved and my parent view and child component code are now correct and functioning Using Vue.js, I'm attempting to iterate analogous to a nested for loop to render a matrix table display. To achieve this I'm attempting to use a nested v-for loop but couldn't get it to work originally.
The data I'm using to build the table exists as a schedule of dates, each coming from a schedule collection in MongoDB. For each given day all the teams play a match against another team. The match data for each team lives in a schedule array in each document.
To pare down the approach and accomplish this I've created a schedule table of all the teams' schedules in the parent view, and passed it off as a property to the child component to streamline the v-for coding.
The traditional pattern for what I'm attempting to do in the child component is logically:
for(const i=0; i<schedules.length; i++) {
for(const j=0; j<weeks.length; j++) {
console.log("This match is " + schedule[i] + " on " + week[j])
On the child component I've tried the following two strategies to no avail:
1.) Wrapping a v-for in a div:
<div v-for="(schedule,j) in schedules" :key="j">
<sui-table-cell v-for="(number, i) in weeks" :key="i">
{{schedules[schedule][i].team}}
</sui-table-cell>
</div>
2.) Wrapping a v-for in a template (this code doesn't compile):
<template v-for="schedule in schedules">
<sui-table-cell v-for="(number, i) in weeks" :key="i">
{{schedules[schedule][i].team}}
</sui-table-cell>
</template>
The data should look like so (if you click on the image you can see where I cannot get this to iterate):
Parent view template.
<template>
<div>
<h1 class="ui header center aligned">ACL</h1>
<h4 class="ui header center aligned schedule">
<em>CRIBBAGE SCHEDULE</em>
</h4>
<sui-table id="standings" class="celled table center aligned">
<inner-table :weeks="totalWeeks" :allPlayers="allPlayers" />
</sui-table>
</div>
</template>
<script>
import TableForm from "./TableForm.vue";
import { api } from "../../../helpers/helpers.js";
export default {
name: "schedule-header",
components: { "inner-table": TableForm },
data() {
return {
totalWeeks: [],
allDates: [],
allPlayers: []
};
},
async mounted() {
this.totalWeeks = await api.getTotalWeeks();
this.allDates = await api.getAllDates();
this.allPlayers = await api.getTeams();
}
};
</script>
<style scoped>
h4.schedule {
color: brown;
}
</style>
Child Component:
<template>
<div>
<sui-table-header>
<sui-table-row>
<sui-table-header-cell></sui-table-header-cell>
<sui-table-header-cell>TEAMS</sui-table-header-cell>
<sui-table-header-cell v-for="(number, i) in weeks" :key="i">WK{{i+1}}</sui-table-header-cell>
</sui-table-row>
<sui-table-row>
<sui-table-cell></sui-table-cell>
<sui-table-cell></sui-table-cell>
<sui-table-cell v-for="(number, i) in weeks" :key="i">{{ number.gameDate.substring(0,10) }}</sui-table-cell>
</sui-table-row>
</sui-table-header>
<sui-table-row v-for="(player, i) in allPlayers" :key="i">
<sui-table-cell>{{i+1}}</sui-table-cell>
<sui-table-cell>{{ player.player1 }}&{{player.player2}}</sui-table-cell>
<sui-table-cell v-for="(week, j) in weeks" :key="j">{{player.schedule[j]}}</sui-table-cell>
</sui-table-row>
</div>
</template>
<script>
export default {
props: ["weeks", "allPlayers"]
};
</script>
Upvotes: 0
Views: 1632
Reputation: 2060
Vue uses key property to differ between components and prevent unnecessary rendering. So from your code :key="i"
, Vue understands that all sui-table-cell
with key i
are the same. That's why you've got repeats. You should provide unique keys to avoid this.
This code would do, however I would not recommend to use index as a key and provide some better keying strategy.
<sui-table-row v-for="(player, i) in allPlayers" :key="i">
<sui-table-cell>{{i+1}}</sui-table-cell>
<sui-table-cell>{{ player.player1 }}&{{player.player2}}</sui-table-cell>
<div v-for="(schedule,j) in schedules" :key="j">
<sui-table-cell v-for="(number, i) in weeks" :key="`${j}_${i}`">
{{schedules[j][i]}}
</sui-table-cell>
</div>
</sui-table-row>
Sample data:
{
schedules: [[1, 2, 3, 4, 5, 6, 7, 8, 9, 10],[2,3,4,5,6,7,8,9,1]]
weeks: [1/1,1/7,1/14,1/21,1/28,2/5,2/12,2/19,2/25,3/3]
}
The solution with template, will not really work, because template
part is never rendered, it is used when you want to use v-for
, for multiple internal elements such as:
<template v-for="...">
<h1></h1>
<p></p>
</template>
Upvotes: 1