Home > Software engineering >  Dynamically add Vue components to an array
Dynamically add Vue components to an array

Time:06-24

I am creating this wizard with a bunch of steps, but the amount of steps depends on what the user selects in step 1 via checkboxes. Step 1 is fixed so it will always be there and so are the last two steps. Between the first and the second last steps are dynamic steps (lets call them components) I get from an array. So on step 1 if I check task 1's checkbox then a tab will appear with task 1's content, but here is my problem I need the tasks I add to the array to be components and not just strings I get from the value property of the checkbox.

Template:

<template>
  <div >
    <ul id="stepsList" >
      <li>
        <div >
          <h3>Setup</h3>
        </div>
        <div >
          <label for="projTitle">Give this project a name</label>
          <input type="text" placeholder="Title of Project" id="projTitle" />
        </div>
        <div >
          <input type="checkbox" v-model="steps" value="Task1" id="addTask1" />
          <label for="addTask1">Task 1</label>
        </div>
        <div >
          <input type="checkbox" v-model="steps" value="Task2" id="addTask2" />
          <label for="addTask2">Task 2</label>
        </div>
        <div >
          <input type="checkbox" v-model="steps" value="Task3" id="addTask3" />
          <label for="addTask3">Task 3</label>
        </div>
        <div >
          <input
            type="checkbox"
            v-model="steps"
            value="Task 4"
            id="addTask4"
          />
          <label for="addTask4">Task 4</label>
        </div>
      </li>
      <li v-for="(step, index) in steps" :key="index">
        <div >
          <h3>{{ step }}</h3>
        </div>
      </li>
      <li>
        <div >
          <h3>Add Docs</h3>
        </div>
      </li>
      <li>
        <div >
          <h3>Publish</h3>
        </div>
      </li>
    </ul>
    <div >
      <button type="button" >Next</button>
    </div>
  </div>
</template>

and here is the script:

<script>
export default {
  data() {
    return {
      steps: [],
    };
  },
};
</script>

I need the steps I add dynamically with the check boxes in step 1 to be components. How can I accomplish it please?

CodePudding user response:

To create components dynamically on checkbox selection, You can do that by using :is attribute. Here is the official documentation.

<li v-for="(step, index) in steps" :key="index">
    <component v-bind:is="step"></component>
</li>

And you can register these components dynamically by putting a watcher on steps array :

Vue.component('Task1', { 
    template: '<div>Task 1 component</div>' 
})

Live Demo :

new Vue({
  el: '#app',
  data: {
    steps: []
  },
  watch: {
    steps: {
      handler() {
        this.steps.forEach(step => {
          Vue.component(step, { 
            template: `<div>${step} component</div>` 
          })
        });
      }
    }
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
  <ul id="stepsList" >
    <li>
      <div >
        <h3>Setup</h3>
      </div>
      <div >
        <label for="projTitle">Give this project a name</label>
        <input type="text" placeholder="Title of Project" id="projTitle" />
      </div>
      <div >
        <input type="checkbox" v-model="steps" value="Task1" id="addTask1" />
        <label for="addTask1">Task 1</label>
      </div>
      <div >
        <input type="checkbox" v-model="steps" value="Task2" id="addTask2" />
        <label for="addTask2">Task 2</label>
      </div>
      <div >
        <input type="checkbox" v-model="steps" value="Task3" id="addTask3" />
        <label for="addTask3">Task 3</label>
      </div>
      <div >
        <input
               type="checkbox"
               v-model="steps"
               value="Task 4"
               id="addTask4"
               />
        <label for="addTask4">Task 4</label>
      </div>
    </li>
    <li v-for="(step, index) in steps" :key="index">
      <component v-bind:is="step"></component>
    </li>
    <li>
      <div >
        <h3>Add Docs</h3>
      </div>
    </li>
    <li>
      <div >
        <h3>Publish</h3>
      </div>
    </li>
  </ul>
</div>

  • Related