Search code examples
vue.js

Vue passing data to child component


I have an issue where I'm trying to pass an object 'through' one component, which is the overall layout, to child components which sit inside it. I've made a simplified example where I basically have a <ul></ul> template and an <li></li> template.

I seem to be losing the reference for each one by the time they are created. When I create them, I get the error:

vue.js:1023 [Vue warn]: Error when evaluating expression "model.id": 
   TypeError: Cannot read property 'id' of undefined (found in component:
   <demo-list-item>)

What am I doing wrong?

I think I just have a fundamental missing from my knowledge of Vue... I'm really, really new to it and am learning from their website – so this could be a really obvious / silly mistake.

HTML:

<div id="app">
    <demo-list></demo-list>
    <script id="demo-list-template" type="text/x-template">
        <ul>
            <demo-list-item v-for="item in items"></demo-list-item>
        </ul>
    </script>
    <script id="demo-list-item-template" type="text/x-template">
            <li data-id="{{model.id}}">{{ model.name }}</li>
    </script>
</div>

JavaScript:

// define
var DemoList = Vue.extend({
    template: '#demo-list-template',
    data : function(){
        return {
            'items' : [
                {
                    'id' : 1,
                    'name' : 'this'
                },
                {
                    'id' : 2,
                    'name' : 'that'
                },
                {
                    'id' : 3,
                    'name' : 'something'
                },
                {
                    'id' : 4,
                    'name' : 'nothing'
                }
            ]
      }
    }
});

// List Item
var DemoListItem = Vue.extend({
    template : '#demo-list-item-template'
});

// register
Vue.component('demo-list', DemoList);
Vue.component('demo-list-item', DemoListItem);

// create a root instance
var Vue = new Vue({
  el: '#app',
});

Demo: http://codepen.io/EightArmsHQ/pen/vXYWgz


Solution

  • According to the Component props doc, you can pass data to child component like this :

    <child name="value"></child>
    

    and

    <child :name="value"></child>
    

    for dynamic props

    So, in your template, when you loop over items array, you got item object. Just pass it to your child component

    <demo-list-item v-for="item in items" :item="item">
    

    Also, in your child component, you have to tell that you attempt to get a prop named item

    var DemoListItem = Vue.extend({
        template : '#demo-list-item-template',
        props: ['item']
    });
    

    You can validate props, set default value, etc (see doc)

    Now, in your child template, you have access to item property

    <li data-id="{{item.id}}">{{ item.name }}</li>