Search code examples
javascripthtmlvue.jsvuejs3vue-component

When i set a v-for, props undefined


I'm doing a website of a League of Legends assist, and i have a component with five elements (one for each line). I had it setted without a v-for, and it worked perfect, but when i configured it with a v-for for future eficiency, it gives me a error of not getting the prop passed by the father.

If i remove the v-for it works perfectly.

Here is the code without the v-for:

<template>
    <div class="champsIconsSelection">
      <button class="champIconSelection" :class="{[lado]: true, picked: (this.rolePicked==='TOP'), setted: (this.champsPicked[0] !== 0)}" @click="pickRole('TOP')">
        <img :src="'/static/icons/'+ this.champsPicked[0] +'.jpg'" v-if="this.champsPicked[0] !== 0">
      </button>
      <button class="champIconSelection" :class="{[lado]: true, picked: (this.rolePicked==='JGL'), setted: (this.champsPicked[1] !== 0)}" @click="pickRole('JGL')">
        <img :src="'/static/icons/'+ this.champsPicked[1] +'.jpg'" v-if="this.champsPicked[1] !== 0">
      </button>
      <button class="champIconSelection" :class="{[lado]: true, picked: (this.rolePicked==='MID'), setted: (this.champsPicked[2] !== 0)}" @click="pickRole('MID')">
        <img :src="'/static/icons/'+ this.champsPicked[2] +'.jpg'" v-if="this.champsPicked[2] !== 0">
      </button>
      <button class="champIconSelection" :class="{[lado]: true, picked: (this.rolePicked==='ADC'), setted: (this.champsPicked[3] !== 0)}" @click="pickRole('ADC')">
        <img :src="'/static/icons/'+ this.champsPicked[3] +'.jpg'" v-if="this.champsPicked[3] !== 0">
      </button>
      <button class="champIconSelection" :class="{[lado]: true, picked: (this.rolePicked==='SUP'), setted: (this.champsPicked[4] !== 0)}" @click="pickRole('SUP')">
        <img :src="'/static/icons/'+ this.champsPicked[4] +'.jpg'" v-if="this.champsPicked[4] !== 0">
      </button>
    </div>
</template>

And here is with the v-for:

<template>
    <div class="champsIconsSelection">
      <div v-for="position in positions" v-bind:key="position.pos">
        <button class="champIconSelection"
                :class="{[lado]: true, picked: (this.rolePicked && this.rolePicked===position.role), setted: (this.champsPicked[position.pos] !== 0)}"
                @click="pickRole(position.role)">
          <img :src="'/static/icons/'+ this.champsPicked[position.pos] +'.jpg'" v-if="this.champsPicked[position.pos] !== 0">
        </button>
      </div>
    </div>
</template>

The rest of the component, in case it's useful:

<script>
export default {
  name: 'champ_selector',
  props: ['lado', 'rolePicked', 'champsPicked'],
  data () {
    return {
      positions: [
        {
          'pos': 0,
          'role': 'TOP'
        },
        {
          'pos': 1,
          'role': 'JGL'
        },
        {
          'pos': 2,
          'role': 'MID'
        },
        {
          'pos': 3,
          'role': 'ADC'
        },
        {
          'pos': 4,
          'role': 'SUP'
        }
      ]
    }
  },
  methods: {
    pickRole (role) {
      this.$emit('pickRole', role)
    }
  }
}
</script>

This is the parent component:

<template>
  <main>
    <div id="champZone">
      <div id="blueChampSelect">
        <champSelect :lado="'blue'" :rolePicked="b_rolePicked" :champsPicked="b_champsPicked" @pickRole="pickRoleB"></champSelect>
      </div>
      <div id="champList">
        <champList @setChamp="setChamp"></champList>
      </div>
      <div id="redChampSelect">
        <champSelect :lado="'red'" :rolePicked="r_rolePicked" :champsPicked="r_champsPicked" @pickRole="pickRoleR"></champSelect>
      </div>
    </div>

    <dataZone></dataZone>
  </main>
</template>

<script>
import champList from './ChampList.vue'
import champSelect from './ChampSelect.vue'
import dataZone from './DataZone.vue'

export default {
  data () {
    return {
      b_rolePicked: '',
      r_rolePicked: '',
      b_champsPicked: [0, 0, 0, 0, 0],
      r_champsPicked: [0, 0, 0, 0, 0],
      roleDict: {'TOP': 0, 'JGL': 1, 'MID': 2, 'ADC': 3, 'SUP': 4}
    }
  },
  components: {
    champList,
    champSelect,
    dataZone
  }
}
</script>

I tried setting something in the variable passed throught the 'rolePicked' prop, but it didn't work either. It feels weird.


Solution

  • You seem to be assuming the this context within the markup. Try changing this.

    <button class="champIconSelection"
                    :class="{[lado]: true, picked: (this.rolePicked && this.rolePicked===position.role), setted: (this.champsPicked[position.pos] !== 0)}"
                    @click="pickRole(position.role)">
              <img :src="'/static/icons/'+ this.champsPicked[position.pos] +'.jpg'" v-if="this.champsPicked[position.pos] !== 0">
            </button>
    

    to this.

    <button class="champIconSelection"
                    :class="{[lado]: true, picked: (rolePicked && rolePicked===position.role), setted: (champsPicked[position.pos] !== 0)}"
                    @click="pickRole(position.role)">
              <img :src="'/static/icons/'+ champsPicked[position.pos] +'.jpg'" v-if="champsPicked[position.pos] !== 0">
            </button>
    

    Notice that I removed the this. prefix you added to the props.