I am implementing Quiz App but here I am facing an issue if I put static data in array the questions are coming.
Data is not coming if i use async in Vue JS 3
But If I Call data from the API the questions are not showing.
when I console the questions are showing in console and not showing in the front end.
For ref please find the attached code and image.
Home.vue (please see fetchQuestionsFromServer function)
<template>
<main >
<!-- quiz container -->
<QuizComplatePage v-if="endofQuiz" />
<div
>
<img
src="@/assets/images/abstract.svg"
alt=""
/>
<!-- contents -->
<div >
<!-- score container -->
<div >
<p >Score</p>
<p >{{score}}</p>
</div>
<!-- timer container -->
<div >
<div
:style= "`width: ${timer}%`"
></div>
</div>
<!-- question container -->
<div
>
<div >
{{currentQuestion.question}}
</div>
</div>
<!-- options container -->
<div >
<!-- option container -->
<div v-for="(choice,item) in currentQuestion.choices" :key="item">
<div
:ref="optionchosen"
@click="onOptionClick(choice,item)"
>
<div
>
<p > 10</p>
</div>
<div >
<!-- option ID -->
<div >{{item}}</div>
<!-- option name -->
<div >{{choice}}</div>
</div>
</div>
</div>
<!-- option container -->
</div>
<!-- progress indicator container -->
<div >
<div ></div>
<p >{{questionCounter}}/{{questions.length}}</p>
</div>
</div>
</div>
</main>
</template>
<script>
import { onMounted, ref } from 'vue'
import QuizComplatePage from './QuizCompleteOverlay.vue'
export default{
components: {
QuizComplatePage
},
setup(){
//data
let canClick = true
let score = ref(0)
let timer = ref(100)
let endofQuiz = ref(false)
let questionCounter = ref(0)
const currentQuestion = ref({
question: '',
answer: 1,
choices: [],
});
const questions = []
const loadQuestion = () =>{
canClick = true
timer.value=100
//Check question array had questions or not
if(questions.length > questionCounter.value){
currentQuestion.value = questions[questionCounter.value]
console.log('Current Question is : ', currentQuestion.value);
questionCounter.value
}else{
endofQuiz.value = true
console.log('Out of Questions');
}
}
//methods
let itemsRef = []
const optionchosen = (element) =>{
if(element){
itemsRef.push(element)
}
}
const clearSelected = (divselected) =>{
setTimeout(()=>{
divselected.classList.remove('option-correct')
divselected.classList.remove('option-wrong')
divselected.classList.add('option-default')
loadQuestion()
},1000)
}
const onOptionClick = (choice,item) =>{
if(canClick)
{
const divContainer = itemsRef[item]
const optionId = item 1
if(currentQuestion.value.answer ===optionId){
console.log('You are Correct');
score.value = 10
divContainer.classList.add('option-correct')
divContainer.classList.remove('option-default')
}else{
console.log('You are Wrong');
divContainer.classList.add('option-wrong')
divContainer.classList.remove('option-default')
}
timer.value=100
canClick=false
//to go next question
clearSelected(divContainer)
console.log(choice,item);
}else{
console.log('Cant Select Option');
}
}
const countDownTimer = () =>{
let interval= setInterval(()=>{
if(timer.value>0){
timer.value--
}else{
console.log('Time is over');
clearInterval(interval)
}
},150)
}
const fetchQuestionsFromServer = async function(){
fetch('https://opentdb.com/api.php?amount=10&category=18&type=multiple')
.then((res) =>{
return res.json()
})
.then((data) =>{
const newQuestions = data.results.map((serverQuestion) =>{
const arrangedQuestion = {
question: serverQuestion.question,
choices: '',
answer: ''
}
const choices = serverQuestion.incorrect_answers
arrangedQuestion.answer = Math.floor(Math.random() * 4 1)
choices.splice(arrangedQuestion.answer-1 , 0 , serverQuestion.correct_answer)
arrangedQuestion.choices = choices
return arrangedQuestion
})
console.log('new formated questions' , newQuestions);
questions.value = newQuestions
loadQuestion()
countDownTimer()
console.log('questions: =>' , questions.value);
})
}
//lifecycle hooks
onMounted(() =>{
fetchQuestionsFromServer()
})
//return
return {
timer,
currentQuestion,
questions,
score,
questionCounter,
loadQuestion,
onOptionClick,
optionchosen,
endofQuiz,
}
}
}
</script>
<style scoped>
.neumorph-1 {
box-shadow: 6px 6px 18px rgba(0, 0, 0, 0.09), -6px -6px 18px #ffffff;
}
.container {
max-width: 400px;
border-radius: 25px;
}
</style>
QuizComplatePage.vue
<template>
<div >
<div >
<p >All DOne!</p>
<p >100% Score</p>
<!-- Buttons -->
<div >
<div >Done</div>
<div >Retry</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'QuizComplatePage'
}
</script>
<style>
</style>
Image.
CodePudding user response:
You are not using value when you need to:
For instance look in this function
questions.length should be questions.value.length
Also currentQuestion.value = questions.value[questionCounter.value]
Start by fixing that.
Everything that is a ref in your setup needs to be accessed by .value in anything inside your setup. Outside your setup it will have this and can be treated normally. Mixing these two up is the most common error.
const loadQuestion = () =>{
canClick = true
timer.value=100
//Check question array had questions or not
if(questions.value.length > questionCounter.value){
currentQuestion.value = questions.value[questionCounter.value]
console.log('Current Question is : ', currentQuestion.value);
questionCounter.value
}else{
endofQuiz.value = true
console.log('Out of Questions');
}
}
CodePudding user response:
Here is my solution
let questions = []
questions = newQuestions
Now I am able to load questions.