I am building a quiz app with Vue 3 and Bootstrap 4.
I have this method for checking if the clicked answer is the (same as the) correct answer:
JavaScript
x
4
1
checkAnswer(answer) {
2
return answer == this.results[this.questionCount]["correct_answer"];
3
}
4
It should be executed upon clicking a list item, as seen below:
JavaScript
1
2
1
<li v-for="answer in answers" @click="checkAnswer(answer)" :class="{'text-white bg-success' : checkAnswer(answer)}">{{answer}}</li>
2
If the clicked answer is correct, the list item should be added the classes text-white bg-success
, otherwise it should be added text-white bg-danger
.
JavaScript
1
78
78
1
const quizApp = {
2
data() {
3
return {
4
questionCount: 0,
5
results: [
6
{
7
question: "The book "The Little Prince" was written by...",
8
correct_answer: "Antoine de Saint-Exupéry",
9
incorrect_answers: [
10
"Miguel de Cervantes Saavedra",
11
"Jane Austen",
12
"F. Scott Fitzgerald"
13
]
14
},
15
{
16
question:
17
"Which novel by John Grisham was conceived on a road trip to Florida while thinking about stolen books with his wife?",
18
correct_answer: "Camino Island",
19
incorrect_answers: ["Rogue Lawyer", "Gray Mountain", "The Litigators"]
20
},
21
{
22
question:
23
"In Terry Pratchett's Discworld novel 'Wyrd Sisters', which of these are not one of the three main witches?",
24
correct_answer: "Winny Hathersham",
25
incorrect_answers: [
26
"Granny Weatherwax",
27
"Nanny Ogg",
28
"Magrat Garlick"
29
]
30
}
31
]
32
};
33
},
34
methods: {
35
nextQuestion() {
36
if (this.questionCount < this.results.length - 1) {
37
this.questionCount++;
38
}
39
},
40
prevQuestion() {
41
if (this.questionCount >= 1) {
42
this.questionCount--;
43
}
44
},
45
checkAnswer(answer) {
46
// check if the clicked anwser is equal to the correct answer
47
return answer == this.results[this.questionCount]["correct_answer"];
48
},
49
shuffle(arr) {
50
var len = arr.length;
51
var d = len;
52
var array = [];
53
var k, i;
54
for (i = 0; i < d; i++) {
55
k = Math.floor(Math.random() * len);
56
array.push(arr[k]);
57
arr.splice(k, 1);
58
len = arr.length;
59
}
60
for (i = 0; i < d; i++) {
61
arr[i] = array[i];
62
}
63
return arr;
64
}
65
},
66
computed: {
67
answers() {
68
let incorrectAnswers = this.results[this.questionCount][
69
"incorrect_answers"
70
];
71
let correctAnswer = this.results[this.questionCount]["correct_answer"];
72
// return all answers, shuffled
73
return this.shuffle(incorrectAnswers.concat(correctAnswer));
74
}
75
}
76
};
77
78
Vue.createApp(quizApp).mount("#quiz_app");
JavaScript
1
88
88
1
#quiz_app {
2
height: 100vh;
3
}
4
5
.container {
6
flex: 1;
7
}
8
9
.quetions .card-header {
10
padding-top: 1.25rem;
11
padding-bottom: 1.25rem;
12
}
13
14
.quetions .card-footer {
15
padding-top: 0.7rem;
16
padding-bottom: 0.7rem;
17
}
18
19
.answers li {
20
cursor: pointer;
21
display: block;
22
padding: 7px 15px;
23
margin-bottom: 5px;
24
border-radius: 6px;
25
border: 1px solid rgba(0, 0, 0, 0.1);
26
background: #fff;
27
}
28
29
.answers li:last-child {
30
margin-bottom: 0;
31
}
32
33
.answers li:hover {
34
background: #fafafa;
35
}
36
37
.pager {
38
list-style-type: none;
39
margin: 0;
40
padding: 0;
41
display: flex;
42
justify-content: space-between;
43
}
44
45
.pager li > a {
46
display: inline-block;
47
padding: 5px 10px;
48
text-align: center;
49
width: 100px;
50
background-color: #fff;
51
border: 1px solid rgba(0, 0, 0, 0.1);
52
border-radius: 999px;
53
text-decoration: none !important;
54
color: #fff;
55
}
56
57
.pager li > a.disabled {
58
pointer-events: none;
59
background-color: #9d9d9d !important;
60
}
61
62
.logo {
63
width: 30px;
64
}
65
66
.nav-item {
67
width: 100%;
68
}
69
70
.card {
71
width: 100%;
72
}
73
74
@media (min-width: 768px) {
75
.nav-item {
76
width: auto;
77
}
78
79
.card {
80
width: 67%;
81
}
82
}
83
84
@media (min-width: 992px) {
85
.card {
86
width: 50%;
87
}
88
}
JavaScript
1
26
26
1
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.4.1/css/bootstrap.min.css" rel="stylesheet" />
2
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
3
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.16.0/umd/popper.min.js"></script>
4
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
5
<script src="https://unpkg.com/vue@next"></script>
6
7
<div id="quiz_app" class="container quetions d-flex align-items-center justify-content-center my-3">
8
<div v-if="results.length" class="card shadow-sm">
9
<div class="card-header bg-light h6">
10
{{results[questionCount]['question']}}
11
</div>
12
<div class="card-body">
13
<ul class="answers list-unstyled m-0">
14
15
<li v-for="answer in answers" @click="checkAnswer(answer)" :class="{'text-white bg-success' : checkAnswer(answer)}">{{answer}}</li>
16
</ul>
17
</div>
18
<div class="card-footer bg-white">
19
<ul class="pager">
20
<li><a href="#" @click="prevQuestion" class="bg-dark" :class="{'disabled' : questionCount == 0}">Previous</a></li>
21
<li class="d-flex align-items-center text-secondary font-weight-bold small">Question {{questionCount + 1}} of {{results.length}}</li>
22
<li><a href="#" class="bg-dark" :class="{'disabled' : questionCount == results.length - 1}" @click="nextQuestion">Next</a></li>
23
</ul>
24
</div>
25
</div>
26
</div>
The problem
To my surprise, the checkAnswer(answer)
method is executed before (and in the absence of) any click.
Question
What am I doing wrong?
Advertisement
Answer
UPDATED
checkAnswer()
is invoked immediately if used outside a handler.
maybe this will help, when checkAnswer()
is called, store the selected answer selectedAnswer
and check if answer is correct isCorrect
, and use these 2 states to compare the looped answers.
JavaScript
1
33
33
1
<li
2
v-for="answer in answers"
3
:key="answer"
4
@click="checkAnswer(answer)"
5
:class="{
6
'text-white bg-success' : (selectedAnswer === answer && isCorrect),
7
'text-white bg-danger' : (selectedAnswer === answer && !isCorrect)
8
}"
9
>
10
{{answer}}
11
</li>
12
13
data() {
14
return {
15
isCorrect: false,
16
selectedAnswer: ''
17
18
}
19
},
20
methods: {
21
checkAnswer(answer) {
22
// check if the clicked anwser is equal to the correct answer
23
this.selectedAnswer = answer
24
25
if (answer == this.results[this.questionCount]["correct_answer"]) {
26
this.isCorrect = true
27
} else {
28
this.isCorrect = false
29
}
30
},
31
}
32
33