Sergey
Sergey

Reputation: 11

Vue.js. Render of different kinds of child components according to a list of conditions

I'm new to not OOP, and VUE.JS especially.

I have a list of conditions, according to them I should show on the page several different kinds of components.

How can I render, for example, 2 TextInput components (or 3.. 10) dynamically and read the entered text in parent after clicking a button?

Thank you in advance.

Upvotes: 1

Views: 102

Answers (2)

Radu Diță
Radu Diță

Reputation: 14191

If you don't know the type of component you need to display you can use dynamic components.

In a nutshell this defers the type of component used at runtime based on a value.

Let's assume you have 2 different type of components

  • TextComponent
  • ImageComponent

You can have a list of items

data () {
 return {
   items: [
     {
      id: 1,
      val: 'something',
      type: 'TextComponent'
     },
     {
      id: 2,
      val: 'something',
      type: 'ImageComponent'
     }
   ]
 }
}

Now you can iterate over the list and display the component based on type

<component v-for="item in items" :key="item.id" :is="item.type" v-model="item.value />

If type is not the exact name of the component, you can translate it inside the :is condition. Something like this.

:is="getComponentFromTag(item.type)"

And then write the conversion method

methods: {
 getComponentFromTag (tag) {
   switch (tag) {
     case 'text':
       return 'TextComponent'
     case 'img':
       return 'ImageComponent'
   }
 }
}

For the example above I'm assuming that items look like this:

items: [
     {
      id: 1,
      val: 'something',
      type: 'text'
     },
     {
      id: 2,
      val: 'something',
      type: 'img'
     }
   ]

Upvotes: 0

AlekseyHoffman
AlekseyHoffman

Reputation: 2694

You didn't provide any code, so I'm not sure what exactly you are trying to do.

If you want to display multiple components, just use v-for and specify conditions in v-if, which will detemine whether this particular component will be rendered:

<input 
  v-for="input in inputs" 
  v-if="input.show"
  v-model="input.model"
  :placeholder="input.label" 
  type="text"
>

<button @click="handleButtonClick()">Button text</button>
data: () => ({
  inputs: [
    { 
      label: 'input 1', 
      model: '',
      show: true
    },
    { 
      label: 'input 2', 
      model: '',
      show: true
    }
  ]
}),
methods: {
  handleButtonClick () {
    console.log(this.inputs)
  }
}

Upvotes: 1

Related Questions