1

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.

3 Answers 3

2

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>

Sign up to request clarification or add additional context in comments.

Comments

1

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>

Comments

0

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>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.