2
votes

I've been trying to get a dynamic component to work that will allow me to render list items individually based on a provided template.
It seems however, that Vue is interpolating the template in the parents scope and not within the dynamicComponent scope.

Simple example:

<dynamicComponent 
    v-for="item in listItems" 
    v-bind:input="item" 
    v-bind:is="{template:'<p>{{input.name}}</p>'}"
</dynamicComponent>

This fails since input is not known in the parents scope.

Is there a way to pass a template dynamically and have it reference variables/properties within the components scope?

Edit: Solution

Turns out I misunderstood the workings of v-bind:is a bit.
It allows you to inline bind/create an anonymous component, not add to/manipulate a referenced component.

The correct solution seems to be:

<component
  v-for="item in listItems"
  v-bind:input="item"
  v-bind:is="{template:'<p>{{input.name}}</p>', props:['input']}">
</component>
1

1 Answers

0
votes

v-bind is used for a component name property, as you have it, it's binding to an object. You can register a custom component like:

component:{
  name: 'my-component',
  template: '<div>...foo...</div>',
},
data () {
    return {
        currentComponent: 'my-component'
    }
}

Then do the following:

<dynamicComponent v-bind:is="current-component">..</dynamicComponent>

Of course, you can register multiple components as needed and then set the currentComponent data property to which ever one you want to render.

Another example:

import Component1 from 'component-1'
import Component2 from 'component-2'
import Component3 from 'component-3'

components: {
     'component-1': Component1,
     'component-2': Component2,
     'component-3': Component3
},
data () {
    return {
        current: 'component-1'
    }
},
methods: {
    someAction (componentName) {
          this.current = componentName
    }
 }