A.Lo.01
A.Lo.01

Reputation: 3

Vue.js - Iterating through data objects on button click

I am trying to create a quiz using vue.js and cannot seem to figure out how to make the "Next" button iterate through my data. The hope is for the screen to display the object containing the question with answers (i.e. questionOne, questionTwo), then show the next object when "Next" is clicked. I have several attempts in the existing code as you will see, but none work.

Quiz Component Template:

<template>
  <div class="quiz-container">
    <div
      class="question-container">
      <h1> {{ currentQuestion.q }} </h1>
    </div>
    <div class="answer-container">
      <v-btn
        v-for="answer in currentQuestion.ans"
        :key="answer"
        outlined
        block
        x-large
        class="answer-btn"
      >
      {{ answer }}
      </v-btn>
    </div>
    <div
      class="navigation flex-row"
    >
      <v-btn text x-large @click="questionNav.curr--">Back</v-btn>
      <v-spacer />
      <v-btn text x-large @click="qNext()">Next</v-btn>
    </div>
  </div>
</template>

Quiz Script:

<script>
  import { mapGetters } from 'vuex';
  export default {
    name: 'quiz',
    computed: {
      ...mapGetters('user', {
        loggedIn: 'loggedIn'
      })
    },
    data: () => ({
      curr: 0,
      currentQuestion: {
         q: 'kasjdn' ,
         ans: ['1', '2', '3']
      },
      questionOne: {
         q: 'How many minutes do you want to spend?' ,
         ans: ['Short (15-20)', 'Medium (20-40)', 'Long (40-60)']
      },
      questionTwo: {
         q: 'What muscle group do you want to focus on?' ,
         ans: ['Upper Body', 'Lower Body', 'Core', 'Full Body']
      },
      questionThree: {
         q: 'What level intensity do you want?' ,
         ans: ['Leisure Walking', 'Speed Walking', 'Jogging', 'Sprinting']
      },
      questionParts: [this.questionOne, this.questionTwo, this.questionThree]
    }),
    methods: {
      questionNav: function () {
        questionParts = [this.questionOne, this.questionTwo, this.questionThree]
        currentQuestion = questionParts[curr]
      },
      qNext: function () {
        this.currentQuestion = this.questionParts[this.curr++]
      }
    }
  }
</script>

As you can see, I have tried a "qNext" method and a "questionNav" method, but neither work. Again, I would like for the "Next" to iterate through [questionOne, questionTwo, questionThree]. I am relatively new to vue, so any help would be greatly appreciated. Thank you!

Upvotes: 0

Views: 911

Answers (2)

paulgv
paulgv

Reputation: 1828

The problem with the current implementation is that you're trying to populate questionParts in a context where questionOne, questionTwo and questionThree aren't accessible, meaning that your questions array will be filled with undefined values.

Overall, what you've done should work as long as you make sure questionParts does contain the question objects. If you want to keep that logic in the data method, here's how you could go about it:

data: () => {
  const questionOne = {
    q: 'How many minutes do you want to spend?' ,
    ans: ['Short (15-20)', 'Medium (20-40)', 'Long (40-60)']
  };
  const questionTwo = {
    q: 'What muscle group do you want to focus on?' ,
    ans: ['Upper Body', 'Lower Body', 'Core', 'Full Body']
  };
  const questionThree = {
    q: 'What level intensity do you want?' ,
    ans: ['Leisure Walking', 'Speed Walking', 'Jogging', 'Sprinting']
  };
  const questionParts = [questionOne, questionTwo, questionThree]
  return {
    curr: 0,
    currentQuestion: {
      q: 'kasjdn' ,
      ans: ['1', '2', '3']
    },
    questionOne,
    questionTwo,
    questionThree,
    questionParts,
  }
},

By declaring a few variables before actually return data()'s value, you're able to properly populate the questionParts array. This should be sufficient to get your quiz to work.

There are a few other improvements that you might want to consider, for example:

  • Instead of declaring questionOne, questionTwo and questionThree objects, you could instantiate an array of questions directly. Given the code example you provided, it doesn't seem especially useful to have each question as a distinct object.
  • currentQuestion could be a computed property that returns the question at index curr. You would then be able to only increment or decrement curr in the click handlers, and the computed property would take care of returning the correct question without you needing to explicitly assign currentQuestion.

Upvotes: 1

jcoleau
jcoleau

Reputation: 1200

qNext: function () {
        this.currentQuestion.q = this.questionParts[this.curr++].q
        this.currentQuestion.ans = this.questionParts[this.curr++].ans
      }

Upvotes: 0

Related Questions