gb_spectrum
gb_spectrum

Reputation: 2301

Vuejs - Proper way to clone an element, and append to DOM

I have a HTML input field to enter some information:

<div id="fruitForm">
    <div class="inputArea">
        <label for="fruit0">Enter Fruit Name</label>
        <input id="fruit0"></input>
    </div>
</div>
<button @click="newInputField">Add More Fruit Input Fields</button>
<button @click="submit">Submit Fruit</button>

And then I handle that click event:

export default {
    data() {
        return {

        }
    },
    methods: {
        newInputField() {
            //Create another input area for users to input fruits
        },
        submit() {
            //Do something here
        }
    }
}

When a user selects the Add More Fruit Input Fields button, it should create a new input area so that the HTML looks like this:

<div id="fruitForm">
    <div class="inputArea">
        <label for="fruit0">Enter Fruit Name</label>
        <input id="fruit0"></input>
    </div>

    <div class="inputArea">
        <label for="fruit1">Enter Fruit Name</label>
        <input id="fruit1"></input>
    </div>
</div>
<button @click="newInputField">Add More Fruit Input Fields</button>
<button @click="submit">Submit Fruit</button>

Now, I've been using traditional DOM manipulation methods via vanilla Javascript to accomplish this... stuff like this:

const inputArea = document.getElementsByClassName('inputArea');

And then I change the id's of the input field, and then I use appendChild to add the new input field to the DOM.

So my question is: how should I be cloning this element with vuejs? I feel I'm not approaching this in the vuejs way. Should I be approaching this like a list and using v-for? Or something else?

Upvotes: 14

Views: 24240

Answers (1)

oniondomes
oniondomes

Reputation: 2063

Avoid direct DOM manipulations with Vue. You can use data property as a model for your template. The answer would be yes, you can and probably should use v-for for what you call cloning:

var demo = new Vue({
  el: '#demo',
  data: {
    counter: 0,
    inputs: [{
      id: 'fruit0',
      label: 'Enter Fruit Name',
      value: '',
    }],
  },
  methods: {
    addInput() {
      this.inputs.push({
        id: `fruit${++this.counter}`,
        label: 'Enter Fruit Name',
        value: '',
      });
    }
  }
});
<script src="https://unpkg.com/[email protected]/dist/vue.js"></script>
<div id="demo">
  <div class="inputArea" v-for="input in inputs" :key="input.id">
    <label :for="input.id">{{input.label}}</label>
    <input :id="input.id" v-model="input.value"></input>
  </div>
  <button @click="addInput">Add input</button>
</div>

Upvotes: 30

Related Questions