Skip to content
Advertisement

Vue js iterating through data sub-properties is not working

I am new to Vue and I am trying to bind an element with a fairly complex data object using Vue with a nested component.

I believe I have set this up correctly according to the documentation but I’m not seeing any examples that match my situation exactly.

The error I’m getting is vue.js:584 [Vue warn]: Property or method "factions" is not defined on the instance but referenced during render. This message is displayed for every json object property that is referenced in the markup. I’m guessing there is something relatively simple here that I’m missing but I cannot determine what that is. Any help is appreciated, thank you!

Here is a fiddle: https://jsfiddle.net/rjz0gfLn/7/

And the code:

var x = {
  "factions": [
    {
      "id": 0,
      "name": "Unknown",
      "img": "Unknown.png"
    },
    {
      "id": 1,
      "name": "Light",
      "img": "Light.png"
    },
    {
      "id": 2,
      "name": "Dark",
      "img": "Dark.png"
    }
  ],
  "roles": [
    {
      "id": 0,
      "name": "Unknown",
      "img": "Unknown.png"
    },
    {
      "id": 1,
      "name": "Assassin",
      "img": "Assassin.png"
    },
    {
      "id": 2,
      "name": "Mage",
      "img": "Mage.png"
    }
  ],
  "cacheDate": 1521495430225
};

console.log("data object", x);

Vue.component("filter-item", {
    template:   `<li class="fitem">
                    <input type="checkbox" class="fcheck" />
                    <img :src="img" class="fimg" />
                    <span class="fname">
                        {{name}}
                    </span>
                </li>`});

Vue.component("filter-items", {
    template: `<ul class="flist">
                    <filter-item v-repeat="factions"></filter-item>
                    <li class="fseperator"/>
                    <filter-item v-repeat="roles"></filter-item>
                </ul>`});

var v = new Vue({
  el: "#filters",
  data: x
});
<nav id="filter-drawer">
  <ul id="filters" class="flist">
        <filter-items></filter-items>
    </ul>
</nav>

Advertisement

Answer

You have to declare every data you want to pass to the children as props in those child components. Additionally you need to pass each prop from the parent using :fieldnameinchild="value" (shorthand for v-bind:fieldnameinchild="value".

In your case, you’ll need to do that in several places:

Parent:

<filter-items :factions="factions" :roles="roles"></filter-items>

And child:

<filter-item v-for="f in factions" :img="f.img" :fimg="f.fimg" :name="f.name" :key="'f'+f.id"></filter-item>
<filter-item v-for="r in roles" :img="r.img" :fimg="r.fimg" :name="r.name" :key="'r'+r.id"></filter-item>

Notice, in vue2 you want to use v-for instead of v-repeat.

Also, add :key to the v-for:

[Vue tip]: : component lists rendered with v-for should have explicit keys. See https://vuejs.org/guide/list.html#key for more info.

See updated fiddle: https://jsfiddle.net/acdcjunior/rjz0gfLn/21/

var x = {
  "factions": [
    {
      "id": 0,
      "name": "Unknown",
      "img": "img.png"
    },
    {
      "id": 1,
      "name": "Light",
      "img": "/a/a6/Light.png"
    },
    {
      "id": 2,
      "name": "Dark",
      "img": "/0/0e/Dark.png"
    }
  ],
  "roles": [
    {
      "id": 0,
      "name": "Unknown",
      "img": "img.png"
    },
    {
      "id": 1,
      "name": "Assassin",
      "img": "/6/69/Assassin.png"
    },
    {
      "id": 2,
      "name": "Mage",
      "img": "/2/20/Mage.png"
    }
  ],
  "cacheDate": 1521495430225
};

console.log("data object", x);

Vue.component("filter-item", {
    template:   `<li class="fitem">
                    <input type="checkbox" class="fcheck" />
                    <img :src="img" class="fimg" />
                    <span class="fname">
                        {{name}}
                    </span>
                </li>`,
  props: ['img', 'fimg', 'name']
                
});

Vue.component("filter-items", {
  template: `<ul class="flist">
            	  <filter-item v-for="f in factions" :img="f.img" :fimg="f.fimg" :name="f.name" :key="'f'+f.id"></filter-item>
            	  <li class="fseperator"/>
               <filter-item v-for="r in roles" :img="r.img" :fimg="r.fimg" :name="r.name" :key="'r'+r.id"></filter-item>
             </ul>`,
  props: ['factions', 'roles']
});

var v = new Vue({
  el: "#filters",
  data: x
});
<script src="https://unpkg.com/vue"></script>

<nav id="filter-drawer">
  <ul id="filters" class="flist">
        <filter-items :factions="factions" :roles="roles"></filter-items>
    </ul>
</nav>
User contributions licensed under: CC BY-SA
1 People found this is helpful
Advertisement