Issues with pushing nested object. Vue Warnings



  • Hello,
    I am creating a form that consists of nested objects (see the object structure below). I want to add questions (from any question’s add button if possible) and for each question, as many answers as possible.
    I encounter issues when I click on the add button. I tried to add a question by clicking on the add button of the initial question (q0): it allows me to create another question (q1) and more. However, if I want to create a question by clicking on (q1), I get the following errors in the console.

    [Vue warn]: Error in event handler for "click": "TypeError: Cannot read property 'questions' of undefined"
    

    I also tried the following with
    this.forms[index].questions[index].answerChoices.push
    I get the following warning:
    [Vue warn]: Error in event handler for "click": "TypeError: Cannot read property 'questions' of undefined"
    I have the following setup in template and script.

        <template>
      <q-page>
              <q-card class="bg-cyan-2 q-ma-xl">
                <q-card-main>
                <div v-for="form in forms" :key="form.id">
                  <q-field class="q-mb-sm" label="Form Title: " helper="Please enter the title of the question.">
                    <q-input v-model="form.name" type="text" clearable />
                  </q-field>
                  <q-card-separator class="q-mb-md q-mt-xl"/>
               <div v-for="(question, index) in form.questions" :key="question.id">
                <q-btn class="q-mb-md" round size="sm" color="amber" icon="add" @click="addRowQuestions(index)" />
                <q-field class="q-mb-sm" label="Question Title: " >
                  <q-input v-model="question.text" />
                </q-field>
                <q-card-separator class="q-mb-md q-mt-xl"/>
                  <div v-for="(answerChoice, index) in question.answerChoices" :key="answerChoice.id">
                    <q-btn class="q-mb-md" round size="sm" color="green" icon="add" @click="addAnswers(index)" />
                    <q-field class="q-mb-sm" label="Answer ID: ">
                      <q-input v-model="answerChoice.answerId" type="number" clearable />
                    </q-field>
                <q-card-separator class="q-mb-md q-mt-xl"/>
                  </div>
               </div>
               </div>
                </q-card-main>
              </q-card>
      </q-page>
    </template>
    
    <script>
    
    export default {
      data () {
        return {
          forms: [
            {
              name: '',
              questions: [
                {
                  text: '',
                  answerChoices: [
                    {
                      answerId: ''
                    }
                  ]
                }
              ]
            }
          ]
        }
      },
      methods: {
        addRowQuestions (index) {
          this.forms[index].questions.push({
            text: '',
            answerChoices: []
          })
        },
        addAnswers (index) {
          this.forms[index].questions[index].answerChoices.push({
            answerId: ''
          })
        }
      }
    }
    </script>
    

    I’ve looked at various sites but am stuck on this.
    I’ve looked at something like this but don’t know how to get and send the respective indexes.

    this.forms[formIndex].questions[questionIndex].answerChoices.push
    

    Any suggestions please to resolve the warnings and correct/improve this form?



  •   <template>
      <q-page>
              <q-card class="bg-cyan-2 q-ma-xl">
                <q-card-main>
                <div v-for="(form, formIndex) in forms" :key="form.id">
                  <q-field class="q-mb-sm" label="Form Title: " helper="Please enter the title of the question.">
                    <q-input v-model="form.name" type="text" clearable />
                  </q-field>
                  <q-card-separator class="q-mb-md q-mt-xl"/>
               <div v-for="(question, questionIndex) in form.questions" :key="question.id">
                <q-btn class="q-mb-md" round size="sm" color="amber" icon="add" @click="addRowQuestions(formIndex)" />
                <q-field class="q-mb-sm" label="Question Title: " >
                  <q-input v-model="question.text" />
                </q-field>
                <q-card-separator class="q-mb-md q-mt-xl"/>
                  <div v-for="(answerChoice, answerIndex) in question.answerChoices" :key="answerChoice.id">
                    <q-btn class="q-mb-md" round size="sm" color="green" icon="add" @click="addAnswers(formIndex, questionIndex)" />
                    <q-field class="q-mb-sm" label="Answer ID: ">
                      <q-input v-model="answerChoice.answerId" type="number" clearable />
                    </q-field>
                <q-card-separator class="q-mb-md q-mt-xl"/>
                  </div>
               </div>
               </div>
                </q-card-main>
              </q-card>
      </q-page>
    </template>
    

    and

        addAnswers (formIndex, questionIndex) {
          this.forms[formIndex].questions[questionIndex].answerChoices.push({
            answerId: ''
          })
        }
    

    Hope that helps! At least it should get you started.



  • Thanks @Hawkeye64 for your help. I’ve been able to follow your suggestion and got it to work.
    My modified working code is below for anyone interested. Note that I have added 2 extra buttons to allow the removal of questions and answers.

                <div v-for="(form, fIndex) in forms" :key="form.id">
                  <q-field class="q-mb-sm" label="Form Title: " helper="Please enter the title of the form.">
                    <q-input v-model="form.name" type="text" clearable />
                  </q-field>
                  <q-card-separator class="q-mb-md q-mt-xl"/>
               <div v-for="(question, qIndex) in form.questions" :key="question.id">
                <q-btn class="q-mb-md" round size="sm" color="amber" icon="add" @click="addRowQuestions(fIndex)" />
                <q-btn class="vertical-top" v-show="qIndex !==0" round size="sm" color="blue" icon="remove" @click="remRowQs(fIndex)" />
                <q-field class="q-mb-sm" label="Question Title: " >
                  <q-input v-model="question.text" />
                </q-field>
                <q-card-separator class="q-mb-md q-mt-xl"/>
                  <div v-for="(answerChoice, aIndex) in question.answerChoices" :key="answerChoice.id">
                    <q-btn class="q-mb-md" round size="sm" color="green" icon="add" @click="addAnswers(fIndex, qIndex)" />
                    <q-btn class="vertical-top" v-show="aIndex !==0" round size="sm" color="negative" icon="remove" @click="remRowAns(fIndex, qIndex)" />
                    <q-field class="q-mb-sm" label="Answer ID: ">
                      <q-input v-model="answerChoice.answerId" type="number" clearable />
                    </q-field>
                <q-card-separator class="q-mb-md q-mt-xl"/>
                  </div>
               </div>
               </div>
    
      methods: {
        addRowQuestions (fIndex) {
          this.forms[fIndex].questions.push({
            qtext: '',
            answerChoices: [
              {
                answerId: ''
              }
            ]
          })
        },
        addAnswers (fIndex, qIndex) {
          this.forms[fIndex].questions[qIndex].answerChoices.push({
            answerId: ''
          })
        },
        remRowQs (fIndex) {
          this.forms[fIndex].questions.splice(fIndex, 1)
        },
        remRowAns (fIndex, qIndex) {
          this.forms[fIndex].questions[qIndex].answerChoices.splice(qIndex, 1)
        }
      }
    }