Reputation: 1980
I created a quiz by using VueJS. However, there is something that blocks me from clicking on radio buttons. It will check another radio button rather than the one that I want.
HTML code
<div id="app">
<h1>{{ quiz.title }}</h1>
<div v-for="(question, index) in quiz.questions" class="question-content">
<div v-show="index === questionIndex" class="question-box">
<h4>{{ question.text }}</h4>
<ol>
<li v-for="response in question.responses">
<label>
<input type="radio"
v-bind:value="response.correct"
v-bind:name="index"
v-model="userResponses[index]"> {{response.text}}
</label>
</li>
</ol>
<button v-if="questionIndex > 0" v-on:click="prev">
Prev
</button>
<button v-on:click="next">
Next
</button>
</div>
</div>
<div v-show="questionIndex === quiz.questions.length">
<h2>
Quiz finished
</h2>
<p>
Total score: {{ score() }} / {{ quiz.questions.length }}
</p>
<button v-on:click="start">
Restart
</button>
</div>
</div>
VueJS code
// A question has one or more answer, and one or more is valid.
var quiz = {
title: 'Quiz',
questions: [
{
text: "1. Which of the following is a category or element of the balance sheet?",
responses: [
{text: 'Expenses'},
{text: 'Gains'},
{text: 'Liabilities', correct: true},
{text: 'Losses'},
]
}, {
text: "2. Which of the following is an asset account?",
responses: [
{text: 'Accounts Payable'},
{text: 'Prepaid Insurance', correct: true},
{text: 'Unearned Revenue'}
]
}
]
};
new Vue({
el: '#app',
data: {
quiz: quiz,
// Store current question index
questionIndex: 0,
// An array initialized with "false" values for each question
// It means: "did the user answered correctly to the question n?" "no".
userResponses: Array(quiz.questions.length).fill(false)
},
// The view will trigger these methods on click
methods: {
// Go to next question
next: function() {
this.questionIndex++;
},
// Go to previous question
prev: function() {
this.questionIndex--;
},
// Return "true" count in userResponses
score: function() {
return this.userResponses.filter(function(val) { return val }).length;
},
// Restart quiz
start: function() {
this.questionIndex = 0;
}
}
});
You can check the live code at : https://jsfiddle.net/dalenguyen/z4rj62c6/1/
Upvotes: 0
Views: 815
Reputation: 1419
Use Nested index for name attribute.
HTML
<div id="app">
<h1>{{ quiz.title }}</h1>
<div v-for="(question, index) in quiz.questions" class="question-content">
<div v-show="index === questionIndex" class="question-box">
<h4>{{ question.text }}</h4>
<ol>
<li v-for="(response, child_index) in question.responses">
<label>
<input type="radio" v-bind:value="response.text" v-bind:name="response.text" v-model="userResponses[index]"> {{response.text}}
</label>
</li>
</ol>
<button v-if="questionIndex > 0" v-on:click="prev">
Prev
</button>
<button v-on:click="next">
Next
</button>
</div>
</div>
<div v-show="questionIndex === quiz.questions.length">
<h2>
Quiz finished
</h2>
<p>
Total score: {{ score() }} / {{ quiz.questions.length }}
</p>
<button v-on:click="start">
Restart
</button>
</div>
</div>
JS: Calculate Correct Ans
score: function() {
correctCount = 0;
that = this;
this.quiz.questions.filter(function(val, i) {
val.userAnswerCorrect = false;
val.userAnswer = that.userResponses[i];
val.responses.filter(function(ans, j) {
if (ans.correct == true && val.userAnswer == ans.text) {
correctCount++;
}
})
});
return correctCount;
}
Demo: https://jsfiddle.net/sumitridhal/esshqr25/
Upvotes: 1
Reputation: 9491
Just doing the following change will make it work:
v-bind:value="response.text"
response.correct
was making all other values undefined, so the radio was getting confused which is the correct value!
I hope that helps!
Upvotes: 0