0

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):

Correct View Of Data

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>
4
  • {{schedule[i].team}} or {{schedules[j][i].team}} should work Commented Mar 19, 2020 at 16:08
  • it would be a bit more helpful if you shared a snippet of what was in schedules and weeks Commented Mar 19, 2020 at 16:12
  • Appreciate your feedback. I've gone ahead and sent a snippet of that data to the images above. Essentially they are both arrays, weeks is an array of 10 dates. Schedules is a table containing rows for each team's matches on a given date. Commented Mar 19, 2020 at 16:42
  • I agree that schedules[j][i].team should work. I cannot get this to iterate however. The template option just repeats everything in one cell. Commented Mar 19, 2020 at 16:52

1 Answer 1

1

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>
Sign up to request clarification or add additional context in comments.

10 Comments

Thanks a lot for your reply. I popped that div in there and got the following error: [Vue warn]: Error in render: "TypeError: Cannot read property 'team' of undefined" I fiddled with it a bit to see if I could troubleshoot it and it wasn't readily apparent what is happening:
Fixed, try now weeks[j].team
Thanks again Alex, I tried it even though it looks exactly the same as what you told me to do previously:) Same results...
Well, with some data it is better :) Try now
Hi Alex, thanks for helping yesterday! I figured out the problem. I had too many v-for's originally and it was throwing things off. I've updated the code above with the solution, and popped a picture in there so you can see how it looks.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.