I have an array of strings like:
questions: [
"Question 1?",
"Question 2?",
"Question 3?",
"Question 4?",
],
Then I have form fields in my data()
like:
legitForm: {
name: '', // this will be equal to question string
answer: '',
description: '',
duration: '',
},
Now, the problem I'm facing is when I fill inputs for any of questions above the same field for other questions gets same value.
Here is my template code:
<div v-for="(question, index) in questions" :key="index">
<form @submit.prevent="legitStore(question)" method="post">
<div >
<div >
<p>
<strong>{{question}}</strong>
</p>
</div>
<div >
<label for="answer">Answer</label>
<select v-model="legitForm.answer" name="answer" id="answer">
<option value="1">Yes</option>
<option value="0">No</option>
</select>
</div>
<div >
<label for="duration">Duration</label>
<input v-model="legitForm.duration" type="text">
</div>
<div >
<label for="description">Description</label>
<textarea style="height: 190px;" type="text" cols="5" rows="10" id="address" v-model="legitForm.description"></textarea>
</div>
</div>
<button type="submit" >
<span >Save</span>
</button>
</form>
</div>
And this is my post method that sends data to backend:
legitStore(question) {
this.legitForm.name = question; // set "name" in `legitForm` to value of `question` string
axios.post('/api/auth/userLegitsStore', this.legitForm, {
headers: {
Authorization: localStorage.getItem('access_token')
}
})
.then(res => {
// reset my data after success
this.legitForm = {
name: '',
answer: '',
description: '',
duration: '',
};
})
.catch(error => {
var errors = error.response.data;
let errorsHtml = '<ol>';
$.each(errors.errors,function (k,v) {
errorsHtml = '<li>' v '</li>';
});
errorsHtml = '</ol>';
console.log(errorsHtml);
})
},
Here is issue screenshot:
Note: I've tried to
- change
legitForm
to array likelegitForm: [],
andlegitForm: [{....}]
- add index to my inputs
v-model
but I've got errors so i wasn't sure what I'm doing wrong, that's why I'm asking here.
CodePudding user response:
If you think of your questions as questions and answers, you can do something like this:
questions: [
{
question: 'Question 1',
answer: null,
description: null,
duration: null,
},
{
question: 'Question 2',
answer: null,
description: null,
duration: null,
},
]
Then when looping through your form, it would be more like this:
<div v-for="(question, index) in questions" :key="index">
<form @submit.prevent="legitStore(question)" method="post">
...
<select v-model="question.answer" name="answer" id="answer">
<option value="1">Yes</option>
<option value="0">No</option>
</select>
...
</form>
</div>
And in the storing function you could send the data in the question instead of this.legitForm
CodePudding user response:
Like you said you tried here:
change
legitForm
to array likelegitForm: []
, andlegitForm: [{....}]
add
index
to my inputsv-model
You are supposed to be doing that.
I would change legitForm
to:
//create legitForms equal to the length of questions
const legitForms = [];
for (i in questions) legitForms.push(
{
name: '', // this will be equal to question string
answer: '',
description: '',
duration: '',
}
);
and in template:
<div v-for="(question, index) in questions" :key="index">
<form @submit.prevent="legitStore(question)" method="post">
<div >
<div >
<p>
<strong>{{question}}</strong>
</p>
</div>
<div >
<label for="answer">Answer</label>
<select v-model="legitForms[index].answer" name="answer" id="answer">
<option value="1">Yes</option>
<option value="0">No</option>
</select>
</div>
<div >
<label for="duration">Duration</label>
<input v-model="legitForms[index].duration" type="text">
</div>
<div >
<label for="description">Description</label>
<textarea style="height: 190px;" type="text" cols="5" rows="10" id="address" v-model="legitForms[index].description"></textarea>
</div>
</div>
<button type="submit" >
<span >Save</span>
</button>
</form>
</div>
CodePudding user response:
<div v-for="(question, index) in questions" :key="index">
In your template you iterate through questions
and within this tag render object legitForm
it all questions will refer to the same 1 object that's why all question have the same data.
You should have had create an array of question contains it own question's content like
<template>
<div v-for="(question, index) in questions" :key="index">
<form @submit.prevent="legitStore(question)" method="post">
...
<div >
<p>
<strong>{{question.id}}</strong>
</p>
</div>
...
<select v-model="question.answer" name="answer" id="answer">
<option value="1">Yes</option>
<option value="0">No</option>
</select>
...
</form>
</div>
</template>
<script>
class QuestionForm {
// pass default value if you want
name = ''
answer = ''
description = ''
duration = ''
id = ''
constructor(form) {
Object.assign(this, form)
}
}
function initQuestions(num) {
// can generate a Set object cause question are unique
return Array.from({ length: num }, (v, i) => i).map(_j => new QuestionForm())
}
export default {
data() {
return {
questions: initQuestions(5), // pass number of question you want to generate
}
}
}
</script>