Reputation: 905
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
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
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
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