Zoe Edwards
Zoe Edwards

Reputation: 13667

VueJS: How to use a binding value within a for loop of an array?

I have an array of strings:

myList: ['First item', 'Second item']

I want to add a third, and more. I have a method that pushes an empty string onto the array:

this.myList.push('')

(Using .push on a Vue object is okay)

It now looks like this:

['First item', 'Second item', '']

Which I can now edit. However, it’s not bound to the array. When another item is added, the value is lost and it returns to an empty string.

var app = new Vue({
  el: '#app',
  data: function() {
    return {
      myList: ['First item', 'Second item']
    }
  },

  methods: {
    remove(index) {
      Vue.delete(this.myList, index)
    },
    add() {
      this.myList.push('')
    }
  }
})
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
<div id="app">
  <p v-for="(listItem, index) in myList" class="my-2 field" :key="index">
    <input
      type="text"
      :value="listItem"
      :key="index"
    />
    <button @click.prevent="remove(index)">✕</button>
  </p>
  <p>
    <button @click.prevent="add()">Add</button>
  </p>
</div>

Tried the following:

As above:

<input
  type="text"
  :value="listItem"
  :key="index"
/>

Without key, same:

<input
  type="text"
  :value="listItem"
/>

With (incorrect) binding, doesn’t echo value:

<input
  type="text"
  :value="myList[index]"
/>

Using v-bind:

<input
  type="text"
  v-bind:value="listItem"
/>

And also with a key:

<input
  type="text"
  v-bind:value="listItem"
  v-bind:key="index"
/>

I’m positive that I’m going about this the wrong way. Hopefully you can see the behaviour that I’m trying to achive.


Update Have just tried using a v-model, but I get this error:

You are binding v-model directly to a v-for iteration alias. This will not be able to modify the v-for source array because writing to the alias is like modifying a function local variable. Consider using an array of objects and use v-model on an object property instead.

Is it perhaps easier to have an array of objects with one value?

Upvotes: 2

Views: 9110

Answers (2)

user2069112
user2069112

Reputation: 91

you should use v-model to have a 2-way binding on your input and you have to use myList[index] cause v-bind directive requires an attribute value and not a v-for alias (as listItem). Try this:

var app = new Vue({
  el: '#app',
  data: function() {
    return {
      myList: ['First item', 'Second item']
    }
  },

  methods: {
    remove(index) {
      Vue.delete(this.myList, index)
    },
    add(listItem) {
      this.myList.push('')
    }
  }
})
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
<div id="app">
  <p v-for="(listItem, index) in myList" class="my-2 field" :key="index">
    {{myList[index]}}
    <input
      type="text"
      v-model="myList[index]"
    />
    <button @click.prevent="remove(index)">✕</button>
  </p>
  <p>
    <button @click.prevent="add()">Add</button>
  </p>
</div>

Upvotes: 5

Ijas Ameenudeen
Ijas Ameenudeen

Reputation: 9259

The input is not bound with the array elements. Try this.

var app = new Vue({
  el: '#app',
  data: function() {
    return {
      myList: ['First item', 'Second item']
    }
  },

  methods: {
    remove(index) {
      Vue.delete(this.myList, index)
    },
    add() {
      this.myList.push('')
    }
  }
})
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
<div id="app">
  <p v-for="(listItem, index) in myList" class="my-2 field" :key="index">
    <input
      type="text"
      v-model="myList[index]"
      :key="index"
    />
    <button @click.prevent="remove(index)">✕</button>
  </p>
  <p>
    <button @click.prevent="add()">Add</button>
  </p>
</div>

JSFiddle : https://jsfiddle.net/32d41epw/2/

Upvotes: 2

Related Questions