Reputation: 39
I have an array, I want to dynamically create objects in the array and v-model
an input to it, this is what my code looks like:
This is the array
new_questions:{
questionrecord: []
}
This is the input
<div class="form-fields" v-for="(field, index) in question_fields">
<div class="form-group">
<select class="form-control" v-model="new_questions.questionrecord[index].questionresponse">
<option value="single_answer">Single Answer (For regular question)</option>
<option value="multiple_answer">Multiple Answer (For situational judgement question)</option>
</select>
</div>
</div>
I expect to have an array that looks like
new_questions:{
questionrecord: [
{
questiontype: "single_answer"
},
{
questiontype: "multiple_answer"
},
...
]
}
But I get an error:
[Vue warn]: Error in render: "TypeError: Cannot read property 'questionresponse' of undefined
How can I achieve this?
Upvotes: 0
Views: 2205
Reputation: 2473
V-Model is only syntactic sugar for @input=".."
and :value=".."
To manipulate data the way you described it might be necessary to distinguish the two and write a setterMethod
that can handle dynamic (and possibly non-existant) properties.
Depending on the structure of your data, on whether you want to handle properties on different nested levels, etc., your setterMethod
can become a little complex. Helpers like lodash.setWith
could help out a bit.
A very specifig example for your case:
<template>
...
<div class="form-fields" v-for="(field, index) in question_fields">
<div class="form-group">
<select class="form-control"
:value="new_questions.questionrecord[index].questionresponse"
@input="setValue($event.target.value, index)"
>
<option value="single_answer">Single Answer (For regular question)</option>
<option value="multiple_answer">Multiple Answer (For situational judgement question)</option>
</select>
</div>
</div>
...
</template>
<script>
export default {
data() {
return {
new_questions: {
questionrecord: [],
}
};
},
created() {
// prepopulate your questionrecord array so you don't throw TypeErrors
const dummyArray = Array(this.question_fields.length);
this.new_questions.questionrecord.push(...dummyArray);
},
methods() {
setValue(value, index) {
const newRecord = {
questionresponse: value,
};
// in order to create responsive array entries in vue, you have to use native array methods - don't set the value by index
// (e.g. this.new_questions.questionrecorcd[index] = newRecord);
this.new_questions.questionrecord.splice(index, 1, newRecord);
// Object properties would need to be created with Vue.set(rootObj, key, value);
}
}
};
</script>
Upvotes: 1
Reputation: 2070
Don't know how looks your question_fields
, but I tested with some dummy values and this code works for me.
new Vue({
el: "#app",
data() {
return {
question_fields: ['test', 'test1'],
new_questions:{
questionrecord: [
{
questiontype: "single_answer"
},
{
questiontype: "multiple_answer"
}
]
}
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div class="form-fields" v-for="(field, index) in question_fields">
<div class="form-group">
<select class="form-control" v-model="new_questions.questionrecord[index].questionresponse">
<option value="single_answer">Single Answer (For regular question)</option>
<option value="multiple_answer">Multiple Answer (For situational judgement question)</option>
</select>
</div>
</div>
<pre>{{new_questions.questionrecord}}</pre>
</div>
Upvotes: 0