Irgend Son Hansel
Irgend Son Hansel

Reputation: 751

Elegant way to use dynamic components with props in Vue

Following case: I have an API outputting all the content for my Page, as well as its structure and so on (for better understanding, imaging an CMS which includes kind of a page builder, where an author can place components by drag and drop to generate pages content, which is delivered to the front-end by that api).

The structure of the api output would look something like:

{content: [
  {component: hero, content: {...} },
  {component: form, content: {...} },
  ...
]}

So to generate related content I would think of using dynamic components like:

<template v-for="item in content">
  <component :is="item.component" />
</template>

However, doing so I would face the problem, that I have to add properties data onto my components somehow, which (as far as I could see) isn't described within the Vue documentation. So now I wonder how to pass props onto dynamic components, which have entirely different props (hero might have an image, form could have input-placeholders, and so on) - any ideas???

Upvotes: 2

Views: 6388

Answers (2)

jordanfb
jordanfb

Reputation: 789

Take a look at v-bind https://v2.vuejs.org/v2/guide/components-props.html#Passing-the-Properties-of-an-Object (same as Vue 3).

Assuming your API includes a props property for each component, then you'd do this:

<component v-for="item in content" :is="item.component" v-bind="item.props"></component>

Upvotes: 3

muka.gergely
muka.gergely

Reputation: 8329

Nowadays it's necessary to state what version of Vue do you work with.

With Vue 2 you could do it like this:

Vue.component('FirstComponent', {
  props: ['title', 'prop1_1'],
  template: `
    <div>
      {{ title }}<br />
      {{ prop1_1 }}
    </div>
  `
})

Vue.component('SecondComponent', {
  props: ['title', 'prop2_1', 'prop2_2'],
  template: `
    <div>
      {{ title }}<br />
      {{ prop2_1 }}<br />
      {{ prop2_1 }}
    </div>
  `
})

new Vue({
  el: "#app",
  data() {
    return {
      items: [
        {
          component: 'FirstComponent',
          props: {
            title: 'First component title',
            prop1_1: 'this is prop 1_1'
          },
        },
        {
          component: 'SecondComponent',
          props: {
            title: 'Second component title',
            prop2_1: 'this is prop 2_1',
            prop2_2: 'this is prop 2_2',
          },
        },
      ]
    }
  },
  template: `
    <div>
      <component
        v-for="(item, idx) in items"
        :key="idx"
        :is="item.component"
        v-bind="item.props"
      ></component>
    </div>
  `
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app"></div>

Upvotes: 0

Related Questions