TK421
TK421

Reputation: 905

vuejs assign multiple input value to json object value

I'm trying to iterate through a JSON object in Vue. The panelfields variable will be assigned to a JSON object, and will change between different JSON objects with varying numbers of key/value pairs.

I can't figure out how to get the value inserted into each input, as it is created. The code is similar to the following:

data() {
  return {
    panelfields:
    [
      {
        fname: "fname1",
        lname: "lname1",
        email: "email1"
      },
      {
        fname: "fname2",
        lname: "lname2",
        email: "email2"
      },
      {
        fname: "fname3",
        lname: "lname3",
        email: "email3"
      }
    ]
  }
}
<div :key="index" v-for="(value, name, index) in panelfields">
  <span>{{ name }}: </span>
  <input type="text" v-model="panelfields" :value="value" />
</div>

Note I am trying to avoid the following pattern, where the field props are explicitly bound by name in the template:

<input type="text" v-model="value.fname" :value="value" />
<input type="text" v-model="value.lname" :value="value" />
<input type="text" v-model="value.email" :value="value" />

...which would force the JSON object pattern to fit that model, requiring separate panels to be created for each JSON object that panelfields is set to.

Panel fields is for a popup panel that will display data for different database queries, and the JSON object will be different depending on what is queried; it may be "fname", "lname", "email" or it may be something else entirely. So the UI needs to be flexible in how it handles the data.

Upvotes: 1

Views: 1848

Answers (3)

tony19
tony19

Reputation: 138656

Use a nested v-for to iterate each field's props by key (obtained by Object.keys(field)), allowing you to dynamically bind the props with v-model="field[key]":

<div :key="index" v-for="(field, name, index) in panelfields">
  <input v-for="key in Object.keys(field)" v-model="field[key]" />
</div>

new Vue({
  el: '#app',
  data() {
    return {
      panelfields: 
      [
        {
          fname: "fname1",
          lname: "lname1",
          email: "email1"
        },
        {
          fname: "fname2",
          lname: "lname2",
          email: "email2"
        },
        {
          fname: "fname3",
          lname: "lname3",
          email: "email3"
        }
      ]
    }
  },
})
<script src="https://unpkg.com/[email protected]/dist/vue.min.js"></script>

<div id="app">
  <div :key="index" v-for="(value, name, index) in panelfields">
    <span>{{name}}: </span>
    <input type="text" v-for="x in Object.keys(value)" v-model="value[x]" />
  </div>
  
  <div>
    <pre>panelfields = {{panelfields}}</pre>
  </div>
</div>

Upvotes: 2

Kamal
Kamal

Reputation: 11

Change your template to this

<div v-for="(value, index) in panelfields" :key="index">
  <span>{{ value.fname }}: </span>
  <input type="text" v-model="value.fname" :value="value" />
  <span>{{ value.lname }}: </span>
  <input type="text" v-model="value.lname" :value="value" />
  <span>{{ value.email }}: </span>
  <input type="text" v-model="value.email" :value="value" />
  <hr>
</div>

Upvotes: 1

Arc
Arc

Reputation: 1078

You can't set an entire array of objects as a v-model. Just make the separate inputs for each v-model.

<div v-for="(item, index) of panelfields" :key="index">
     <span>{{item.fname}}</span><input v-model="panelfieds[index].fname"/>
     <span>{{item.lname}}</span><input v-model="panelfieds[index].lname"/>
     <span>{{item.email}}</span><input v-model="panelfieds[index].email"/>
</div>

Upvotes: 0

Related Questions