Home » vue » Vue js component with nested data

Vue js component with nested data

Posted by: admin November 26, 2021 Leave a comment

Questions:

This is driving me crazy, I have nested data in an array and have not been successful in getting it to render using components, I am able to render it without a component though.

var data2 = {
    "team": [{
        "id":0,
        "author": "Johnnie Walker",
        "title": "Aging Your Own Whisky",
        "content": "A bunch of steps and a whole lot of content",
        "members": [
            {
              "id": "0",
              "name": "name 1",
              "text": "bio"
            },
            {
              "id": "1",
              "name": "name 2",
              "text": "bio"
            }
            ]
        },
        {
        "id":1,
        "author": "Captain Morgan",
        "title": "Rum stories",
        "content": "A bunch of steps and a whole lot of contentttt",
        "members": [
            {
              "id": "3",
              "name": "name 3",
              "text": "bio"
            }
            ]               
        }               
    ]}

What I am trying to do is loop through members, here is my current code

index.html

<div id="app2">
    <entry v-for="t in team" v-bind:cat="t" v-bind:key="t.id">
        <detail v-for="mem in t.members" v-bind:ember="mem" v-bind:key="mem.id"></detail> 
    </entry>
</div>

and here is my js file

    Vue.component('entry', {
        props:['cat'],
        template: '<div>{{cat.author}}</div>'
    })

    Vue.component('detail', {
        props:['ember'],
        template: '<div>{{ember.id}}</div>',
    })

    var vm2 = new Vue({
        el: '#app2',
        data: function() {
            console.log(data2.team)
            return data2;
        }           
    });

The data in entry renders but nothing happens with detail, no warnings either, how do I proceed?

Note: When I approach it this way it DOES work, but this is not using a component:

    var vm = new Vue({
        el: '#app',
        data: function() {
            console.log(data2.team)
            return data2;
        }           
    });

and the html

<div id="app">
    <div v-for="t in team" v-bind:key="t.id" v-bind:author="t.author">
    {{t.author}}
        <div v-for="m in t.members" v-bind:key="m.id">
            {{m.name}}
        </div>   
    </div>  
</div>
Answers:

You either need to add the detail component to the entry template, or you need to add a slot to the entry component.

Here is your code modified to use a slot.

console.clear()
var data2 = {
  "team": [{
      "id": 0,
      "author": "Johnnie Walker",
      "title": "Aging Your Own Whisky",
      "content": "A bunch of steps and a whole lot of content",
      "members": [{
          "id": "0",
          "name": "name 1",
          "text": "bio"
        },
        {
          "id": "1",
          "name": "name 2",
          "text": "bio"
        }
      ]
    },
    {
      "id": 1,
      "author": "Captain Morgan",
      "title": "Rum stories",
      "content": "A bunch of steps and a whole lot of contentttt",
      "members": [{
        "id": "3",
        "name": "name 3",
        "text": "bio"
      }]
    }
  ]
}
Vue.component('entry', {
  props: ['cat'],
  template: '<div>{{cat.author}}<slot/></div>'
})

Vue.component('detail', {
  props: ['ember'],
  template: '<div>{{ember.id}}</div>',
})

var vm2 = new Vue({
  el: '#app2',
  data: function() {
    console.log(data2.team)
    return data2;
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.js"></script>
<div id="app2">
  <entry v-for="t in team" v-bind:cat="t" v-bind:key="t.id">
    <detail v-for="mem in t.members" v-bind:ember="mem" v-bind:key="mem.id">
    </detail>
  </entry>
</div>

And here it is modifying the entry component to include the detail.

console.clear()
var data2 = {
  "team": [{
      "id": 0,
      "author": "Johnnie Walker",
      "title": "Aging Your Own Whisky",
      "content": "A bunch of steps and a whole lot of content",
      "members": [{
          "id": "0",
          "name": "name 1",
          "text": "bio"
        },
        {
          "id": "1",
          "name": "name 2",
          "text": "bio"
        }
      ]
    },
    {
      "id": 1,
      "author": "Captain Morgan",
      "title": "Rum stories",
      "content": "A bunch of steps and a whole lot of contentttt",
      "members": [{
        "id": "3",
        "name": "name 3",
        "text": "bio"
      }]
    }
  ]
}


Vue.component('detail', {
  props: ['ember'],
  template: '<div>{{ember.id}}</div>',
})

Vue.component('entry', {
  props: ['cat'],
  template: `<div>
    {{cat.author}}
    <detail v-for="mem in cat.members" v-bind:ember="mem" v-bind:key="mem.id">
    </detail>
    </div>`
})


var vm2 = new Vue({
  el: '#app2',
  data: function() {
    return data2;
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.js"></script>
<div id="app2">
  <entry v-for="t in team" v-bind:cat="t" v-bind:key="t.id"></entry>
</div>