Skip to content
Advertisement

Vue Component Props only available on $vnode

I’m new to the World of Vue.js and I have to build a recursive Component renderer that turns JSON into rendered Vue components.

So far the recursive rendering works just fine, except for the props I’m passing to the createElement function (code below 😉 ) is not available as props, but inside the $vnode.data object. Any ideas what I’m missing?

The mock JSON I’m using looks like this:

{
  "_id": "aslwi2",
  "template": "NavigationBar",
  "data": {},
  "substructure": [
    {
      "_id": "assd2",
      "template": "NavigationBarListItem",
      "data": {
        "title": "NavList Item 1"
      }
    },
    {
      "_id": "a2323uk",
      "template": "NavigationBarListItem",
      "data": {
        "title": "NavList Item 2"
      }
    }
  ]
}

My Recursive Rendering Component:

const createComponent = function(node ,h){
    if(!node || !node.template){
        return;
    }

    let children = [];
    if(node.substructure instanceof Array){
        node.substructure.map( async childNode => {
            const childComponent = createComponent(childNode, h);
            children.push(childComponent);
        });
    }

    return h(node.template, {xdata : clone(node.data)}, children.length > 0 ? children : null );
};



export default Vue.component('Structure', {
    render: function(createElement){

        if(!this.structure) return;
        const component =  createComponent(this.structure, createElement, registry);
        console.log(component);
        return component;
    },
    props: {
        structure: {
            type: Object
        }
    }
})

And my dynamically instantiated components:

<!-- Component: NavBar -->
<template>
    <div class="nav-bar">
        <slot></slot>
    </div>
</template>

<script>
    export default {
        props: {
            data: {
                type: Object
            }
        }
    }
</script>

<!-- Component: NavBarListItem -->
<template>
    <div class="nav-bar-item">
        {{title}}
    </div>
</template>

<script>
    export default {
        data () {
            return {
                title : "default"
            }
        },
        created() {
            console.log('list item: ', this)
        }
    }
</script>

Inside the log of the created method in my list item component we find the passed props within the $vnode…

Props available in $vnode but not as props

Advertisement

Answer

The problem is here:

return h(node.template, {xdata : clone(node.data)}, ...

I don’t know what xdata is but it isn’t something you should be passing to h. The options are documented at https://v2.vuejs.org/v2/guide/render-function.html#The-Data-Object-In-Depth.

To pass a props you’d use props.

return h(node.template, {props : clone(node.data)}, ...

While I’m struggling a little to follow the intent behind your code it looks like you may also have a problem with NavBarListItem not defining a title prop. You can’t pass a title unless it’s defined as a prop. Defining it in data isn’t the same thing.

User contributions licensed under: CC BY-SA
9 People found this is helpful
Advertisement