Home > Back-end >  Vuejs get index in multiple input forms
Vuejs get index in multiple input forms

Time:05-13

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:

one

Note: I've tried to

  1. change legitForm to array like legitForm: [], and legitForm: [{....}]
  2. 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 like legitForm: [], and legitForm: [{....}]

add index to my inputs v-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>
  • Related