I'm having an error when defining event click and function "select answer". I think it comes from JS
Console error: "[Vue warn]: Property or method 'selectAnswer' is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property. See: https://v2.vuejs.org/v2/guide/reactivity.html#Declaring-Reactive-Properties. (found in )"
"[Vue warn]: Invalid handler for event 'click': got undefined
(found in )"
HTML
<h1 class="main">Quiz app in Vue</h1>
<div id="question">
<div id="function">
<div class="user-role">
<div class="question current">
<transition name="slide-fade" mode="out-in">
<div :key="questions[currentQuestion].question" :class="{'deactivate': answered == questions.length}">
<h2>{{ questions[currentQuestion].question }}</h2>
<div class="answers">
<span v-for="(answer, index) in questions[currentQuestion].answers" :key="index" v-bind:data-index="index" @click="selectAnswer">{{ answer }}</span>
</div>
</div>
</transition>
<div class="next-question">
<button class="next-btn" disabled>{{ currentQuestion < (questions.length -1) ? 'Next' : 'Result!' }}</button>
</div>
</div>
<div class="result">
<div class="success"></div>
<h2>You have successfully finished the quiz, and your score is:</h2>
<h1 :class="[(Number(((correctAnswers / questions.length) *100)).toFixed(2) >= 50) ? 'green' : 'red']">{{ Number(((correctAnswers / questions.length) *100)).toFixed(2) }}%</h1>
<small><b>{{ correctAnswers }}</b>Correct, <b>{{ wrongAnswers }}</b>Wrong</small>
<button class="close">close</button>
<button class="show-wrong-ones"
v-show="wrongAnswers > 0"
@click="showWrongQuestion = true">Wrong answers</button>
</div>
</div>
<div class="wrong-questions">
<h2 v-if="wrongQuestions.length > 1">Your wrong Questions</h2>
<h2 v-else-if="wrongQuestions.length == 1">Your wrong Question</h2>
<div class="wrong-one" v-for="question in wrongQuestions">
<h3>{{ question.question }}</h3>
<div class="answers-container">
<span class="selected">{{ question.answers[question.selected] }}</span>
<span class="correct">{{ question.answers[question.correct_answer] }}</span>
</div>
</div>
<button id="return-to-result">Show my result</button>
</div>
</div>
</div>
JS
Vue.component ("function",{
data: function ()
{
},
method: {
selectAnswer: function(a) {
var choice = a.currentChoice,
answers = document.querySelectorAll('.answers span'),
nextBtn = document.querySelector('.nextbtn');
//? : -> Tenary Operator
answers.forEach(answer => {
answer.contains('selected') ? answer.remove('selected') : '';
});
choice.classList.add('selected');
this.questions[this.currentQuestion].selected = choice.dataset.index;
nextBtn.removeAttribute('disabled');
},
calculateResult: (questions) => {
var correct;
for(var i=0; i< questions.length; i++) {
this.questions[i].selected == questions[i].correct ? correct++ : '';
}
}
},
mounted() {
var nextBtn = this.$el.querySelector('.next-btn'),
answers = this.$el.querySelectorAll('.answers span'),
questionsLength = this.questions.length,
result = this.$el.querySelector('.result'),
question = this.$el.querySelector('.question'),
closeResult = this.$el.querySelector('.result button.close'),
wrongQuestions = this.$el.querySelector('.wrong-questions'),
showMyResults = this.$el.querySelector('#return-to-result');
nextBtn.addEventListener('click', () => {
this.answered < this.questions.length ? this.answered++ : '';
if(!nextBtn.hasAttribute('disabled') && this.currentQuestion < (questionsLength -1)) {
this.currentQuestion++;
answers.forEach(answer => { answer.classList.contains('selected') ? answer.classList.remove('selected') : '';
});
nextBtn.setAttribute('disabled', '');
} else if(this.currentQuestion >= (questionsLength -1)) {
this.questions.forEach( (question) => {
if(question.selected == question.correct_answer && question.sense ==0) {
this.correctAnswers++;
question.sense = 1;
} else if(question.selected != question.correct_answer && question.sense ==0) {
this.wrongAnswers++;
question.sense = 1;
let temp = {};
temp.answers = question.answers;
temp.question = question.question;
temp.correct_answer = question.correct_answer;
temp.selected = question.selected;
this.wrongQuestions.push(temp);
}
});
result.classList.add('active');
question.classList.add('blur');
}
});
closeResult.addEventListener('click', () => {
result.classList.remove('active');
question.classList.remove('blur');
});
},
})
new Vue ({
el: "#question",
data() {
return {
questions: [
{
question: 'What is the capital of Ukrain ?',
answers: [
'Kyiv',
' Kabul',
' Buenos Aires',
' Praia'
],
correct_answer: 0,
selected: null,
sense: 0
},
{
question: 'When was Queen Elizabeth II death ?',
answers: [
'11/09/2022',
'08/09/2022',
'12/08/2022',
'07/09/2022'
],
correct_answer: 1,
selected: null,
sense: 0
},
{
question: 'How many bones are there in human body?',
answers: [
'206',
'186',
'209',
'190'
],
correct_answer: 0,
selected: null,
sense: 0
},
{
question: 'Who were the 30th president of ?',
answers: [
'Julia Eileen Gillard',
'John Winston Howard ',
' Scott John Morrison ',
'Anthony Albanese,'
],
correct_answer: 2,
selected: null,
sense: 0
},
{
question: 'What is the biggest continent?',
answers: [
'Oceania',
'Europe',
'Asia',
'Africa'
],
correct_answer: 2,
selected: null,
sense: 0
}
],
showWrongQuestion: false,
wrongQuestions: [],
temp: [],
currentQuestion: 0,
answered: 0,
wrongAnswers: 0,
correctAnswers: 0,
}
},
});