user6269864
user6269864

Reputation:

Create a two-way binding in vue.js between an array and multiple text inputs

My data is stored in an array. For each array item, there should be a text input in the form. When the user types into one of the text inputs, the array should be updated with the new values.

  <div class="form-group" v-for="synonym in row.synonyms">
    <input type="text" class="form-control" v-model="synonym" />
  </div>

Here's a fiddle: https://jsfiddle.net/eywraw8t/122210/

The idea is when you type into one of the textboxes, the array value (shown below in that fiddle) should also update, but it doesn't.

Upvotes: 7

Views: 4450

Answers (3)

gotnull
gotnull

Reputation: 27214

This is the recommended way that Vue.js wants you to do it by using an index (synonym, index):

https://v2.vuejs.org/v2/guide/list.html

<div class="form-group" v-for="(synonym, index) in row.synonyms">
  <input type="text" class="form-control" v-on:blur="onItemsChanged(synonym)" v-model="row.synonyms[index]" />
</div>

If you wanted to do it another way you could introduce a method v-on:blur:

new Vue({
  el: "#app",
  data: {
    row: {
        synonyms: [
        "abc", 
        "def", 
        "ghj",
      ]
    }
  },
  methods: {
    onItemsChanged (synonym) {
      // do something with array
    }
  }
})

Upvotes: 0

Derek Pollard
Derek Pollard

Reputation: 7165

Upon inspecting the console, you would find the following 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.

Meaning, we need to give v-model access to a direct reference to the synonym and its index:

new Vue({
  el: "#app",
  data: {
    row: {
    	synonyms: [
      	"abc", 
        "def", 
        "ghj",
      ]
    }
  },
  methods: {

  }
})
body {
  font-family: 'Exo 2', sans-serif;
}

#app {
  margin: auto;
}
<div id="app">
  <h2>Items</h2>
  <div class="form-group" v-for="(synonym,i) in row.synonyms">
    <input type="text" class="form-control" v-model="row.synonyms[i]" />
  </div>
  
  <br>
  
  <h3>
  The text below should change if yout type inside the textboxes:
  </h3>
  
  <p>
  {{ JSON.stringify(row)}}
  </p>
</div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>

Upvotes: 4

user6269864
user6269864

Reputation:

The correct way to do it is to use an index, which vue.js provides in loops:

  <div class="form-group" v-for="(synonym, index) in row.synonyms">
    <input type="text" class="form-control" v-model="row.synonyms[index]" />
  </div>

https://jsfiddle.net/m14vd89u/1/

Upvotes: 2

Related Questions