Aaranihlus
Aaranihlus

Reputation: 149

Vue.JS how to access object properties in component loop

I have a list of items as a component:

Vue.component('building-list', {

    template: `<div><building v-for="building in buildings">{{ building.id }}</building></div>`,

    data() {

        return {

                buildings: {

                    'scavenger': { id: 'scavenger', name: "desh scavenger", amount_owned: 0, cost: 10, base_cps: 1, description: "A scavenger, specialising in the aquisition of Desh" },
                    'vaporator': { id: 'vaporator', name: "moisture farm", amount_owned: 0, cost: 50, base_cps: 2 },
                    'cantina': { id: 'cantina', name: "cantina", amount_owned: 0, cost: 650, base_cps: 3 },
                    'bazaar': { id: 'bazaar', name: "bazaar", amount_owned: 0, cost: 7800, base_cps: 4 },
                    'droidshop': { id: 'droidshop', name: "droid workshop", amount_owned: 0, cost: 80000, base_cps: 5 },
                    'bountyhunter': { id: 'bountyhunter', name: "bounty hunter guild", amount_owned: 0, cost: 140000, base_cps: 6 },
                    'kybermine': { id: 'kybermine', name: "kyber crystal mine", amount_owned: 0, cost: 250000, base_cps: 7 }

                }
        }

    }
        
});

and each of those items i want to look like this:

Vue.component('building', {

    template: `

        <div :key="building[id]" class="card" style="display: block;" v-on:click="buy_building(building[id])"> 
            <img :src="building[id]" style="cursor: pointer; width:100%; height:145px;">
            <div class="card-block">
                <h4 class="card-title">{{ building[name] }}</h4>
                <p class="card-text">cost: {{ building[cost] }}</p>
                <p class="card-text">owned: {{ building[amount_owned] }}</p>
            </div>
        </div>`

});

        <div class="container-fluid">

            <building-list></building-list>

        </div>

When I try to run this, I get this error for each item:

"Property or method "building" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property. See: https://v2.vuejs.org/v2/guide/reactivity.html#Declaring-Reactive-Properties."

I am very new to Vue, so I followed the link to the documentation, however it doesn't really explain how to do this in this particular way, from the tutorials I have been following, this looks right, however again, those tutorials don't really explains things for this situation.

Is this even the right way of doing this?

Upvotes: 2

Views: 3796

Answers (1)

Sergei
Sergei

Reputation: 1023

  1. You must use props for pass data from parent component to child component.
  2. You can use 'dot notation' for access to object properties. If you want to get access with bracket notation you should write string like obj['property']. Read property accessors

Vue.component('building', {
  props: ['building'],
  template: `
        <div :key="building.id" class="card" style="display: block;" v-on:click="buy_building(building.id)">
            <div class="card-block">
                <h4 class="card-title">{{ building.name }}</h4>
                <p class="card-text">cost: {{ building.cost }}</p>
                <p class="card-text">owned: {{ building.amount_owned }}</p>
            </div>
        </div>
        `,
  methods: {
    buy_building(itemId) {
      alert(itemId);
    }
  }
});

new Vue({
  el: 'building-list',
  template: `<div><building v-for="item in buildings" :building='item' :key='item.id'></building></div>`,
  data() {

    return {

      buildings: {
        'scavenger': {
          id: 'scavenger',
          name: "desh scavenger",
          amount_owned: 0,
          cost: 10,
          base_cps: 1,
          description: "A scavenger, specialising in the aquisition of Desh"
        },
        'vaporator': {
          id: 'vaporator',
          name: "moisture farm",
          amount_owned: 0,
          cost: 50,
          base_cps: 2
        },
        'cantina': {
          id: 'cantina',
          name: "cantina",
          amount_owned: 0,
          cost: 650,
          base_cps: 3
        },
        'bazaar': {
          id: 'bazaar',
          name: "bazaar",
          amount_owned: 0,
          cost: 7800,
          base_cps: 4
        },
        'droidshop': {
          id: 'droidshop',
          name: "droid workshop",
          amount_owned: 0,
          cost: 80000,
          base_cps: 5
        },
        'bountyhunter': {
          id: 'bountyhunter',
          name: "bounty hunter guild",
          amount_owned: 0,
          cost: 140000,
          base_cps: 6
        },
        'kybermine': {
          id: 'kybermine',
          name: "kyber crystal mine",
          amount_owned: 0,
          cost: 250000,
          base_cps: 7
        }

      }
    }

  }

});
    .card {
      outline: 1px solid aquamarine;
      width: 200px;
    }
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<div class="container-fluid">
  <building-list></building-list>
</div>

Upvotes: 4

Related Questions