Žilvinas
Žilvinas

Reputation: 150

Dynamic number of rows containing dynamic number of input fields vue

I trying to create a form which would have a dynamic number of steps. An additional step can be added on click of a button. Inside that step, there are a couple of input fields but also few more buttons to create more input fields.

For example, there are the title and description inputs but also link to Add a Video which would create another input field and would change that link to Remove the Video.

All these steps have to create one array of objects where each object might contain slightly different properties. I'm new to vue and it's very confusing.

<div v-for="(row, index) in rows" :key="index">

<input type="text" v-model="row.title">
<input type="text" v-model="row.description">
<div v-show="row.video">
    <input type="text" v-model="row.video">
</div>
    <a v-on:click="addVideo(index);" style="cursor: pointer">Add Video element</a><br>

<a v-on:click="removeElement(index);" style="cursor: pointer">Remove</a>
</div>
<div>
    <button class="button btn-primary" @click="addRow">Add Step</button>
</div>

and my functions:

addRow () {
  this.rows.push({
    title: '',
    description: '',
    file: {
      name: 'Choose File'
    }
  })
},
addVideo (index) {
  this.rows[index].video = ' '
  this.$forceUpdate()
},
removeElement (index) {
  this.rows.splice(index, 1)
}

or code at this link: http://jsbin.com/punekukayu/1/edit?html,js,output

At this point I don't know how could I remove the Add Video element link from that step and I suppose this is the bad practice approach here.

Upvotes: 1

Views: 1045

Answers (1)

acdcjunior
acdcjunior

Reputation: 135762

You could use v-if and v-else:

<a v-if="input.video === null" v-on:click="addVideo(index);" style="cursor: pointer">Add Video element</a>
<template v-else>
    <input type="text" v-model="input.video">
    <a v-on:click="removeVideo(index);" style="cursor: pointer">Remove Video element</a>
</template>

And you would add video as null by default, so you don't need to call $forceUpdate:

addRow() {
  this.inputs.push({
    one: '',
    two: '',
    video: null                     // added
  })
},
addVideo (index) {
  this.inputs[index].video = '';    // changed
},
removeVideo (index) {
  this.inputs[index].video = null;  // added
},

Updated JSBin here.


If I may suggest, you should pass each input directly to addVideo or removeVideo (instead of index). I think it makes the code simpler: http://jsbin.com/pucohawuje/1/edit?html,js,output - But I do understand this could be a matter of taste, so I'm leaving it just as suggestion.

Upvotes: 1

Related Questions