How to Develop Frontend Quiz App using VueJS? www.bacancytechnology.com
Tutorial Goal: How to Develop Frontend Quiz App using VueJS
In this tutorial, we will learn and explore the fundamental concepts of how can we develop a frontend quiz app using VueJS. We all know how famous the VueJS framework is. Watch the below video to get idea of what are we developing.
So, without further ado, let’s get started with coding.
Create VueJS app
Here, we will be using Vue 2. Run the below command to create the VueJs app.
vue create quiz-app
You’ll see something like this.
Now, with the help of the following command navigate to the directory and run the server. cd quiz-add npm run serve
The localhost will display the default screen as shown below.
Create User Interface
Every Vue component consists of three sections: < template > containing HTML code of the component < script > containing business logic < style > containing CSS code for styling of the component For our demo application, we will be having two components: Quiz component Modal component
Folder Structure Here’s the image of our folder structure. It will be a pretty simple structure.
Now let’s take a look at different files and see what are we going to do. Keep the note of the filename.
In search of dedicated VueJS developers with extraordinary problem-sloving skills and VueJS expertise? Contact Bacancy: the best VueJS development company and start developing your project.
App.vue Set Up
App.vue is the parent file of all the components (here Quiz and Modal component). Let’s define our components. Refer to the following code for the UI template. <template> <div id="app"> <h2>Quiz App</h2> <quiz @quizcompleted="handleQuizCompleted" :key="quizKey" /> <custom-modal v-show="showModal" header="Congratulations!" subheader="You've completed your Quiz!" :score="score" @reload="updateQuiz" @close="showModal = false"
/> </div> </template>
Explanation The code is quite simple. v – show=” show Modal” will render the modal conditionally based on this . showmodal. The score is a dynamic prop sent to modal from data properties. The header and subheader are two static props. The reload and close are the custom events that is called from modal-footer . Moving on the < script > tag.
<script> import CustomModal from "./components/CustomModal.vue"; import Quiz from "./components/Quiz.vue"; export default { components: { Quiz, CustomModal }, name: "App", data() { return { quizKey: 0, showModal: false, score: { allQuestions: 0, answeredQuestions: 0, correctlyAnsweredQuestions: 0, }, }; },
methods: { handleQuizCompleted(score) { this.score = score; this.showModal = true; }, updateQuiz() { this.showModal = false; this.quizKey++; }, }, }; </script>
Explanation The logic will have two methods 1. handle Quiz completed ( ) : It receives the user score from the Quiz component and sets it to local state ‘this . score’. It is triggered by the custom event ‘quizcompleted’ that we’ve ] defined in the Quiz component. 2. update Quiz( ): The method will bind key to the ‘quiz Key’ data property. It will increment the ‘quiz Key’ by one that is further triggered by the ‘reload’ event from the CustomModal component.
Create Components
Further moving ahead with our tutorial to develop frontend quiz app using VueJS. Next we will start with our components: Quiz Component and CustomModal Component.
CustomModal.vue The file CustomModal.vue will consist the UI and logic code of the modal. Refer to the code below. <template> <transition name="modal"> <div class="modal-mask"> <div class="modal-wrapper"> <div class="modal-container"> <div class="modal-header"> <h2>{{ header }}</h2> <h3>{{ subheader }}</h3> </div> <div class="modal-body"> <div id="score"> You answered <span class="highlight"> {{
Math.floor( (score.correctlyAnsweredQuestions / score.allQuestions) * 100 ) }} % correctly! </span> Answered <span class="highlight"> {{ score.correctlyAnsweredQuestions }} out of {{ score.allQuestions }} </span> questions. </div> </div>
<div class="modal-footer"> <button id="play-again" class="button-footer" @click="$emit('reload')" > Play Again </button> <button id="close-button" class="button-footer" @click="$emit('close')" > Close </button> </div> </div> </div> </div> </transition> </template>
<script> export default { props: { header: String, subheader: String, score: Object, }, }; </script>
Explanation The score prop contains how many questions the user answered correctly and also contains total number of questions. We use the score prop received from the Quiz component’s custom events. The modal-footer will have two buttons emitting custom events to reload and close the modal.
Quiz.vue <template> <div class="container"> <div class="correctAnswers"> You have <strong>{{ correctAnswers }} correct {{ pluralizeAnswer }}!</strong> </div> <div class="correctAnswers"> Currently at question {{ index + 1 }} of {{ questions.length }} </div> <h1 v-html="loading ? 'Loading...' : currentQuestion.question"></h1> <!-- Only first question is displayed -> <form v-if="currentQuestion">
<button v-for="answer in currentQuestion.answers" :index="currentQuestion.key" :key="answer" v-html="answer" @click.prevent="handleClick" ></button> </form> </div> </template>
Explanation “loading ? ‘Loading…’ : currentQuestion.question” will check the loading property and based on it will decide ‘Loading…’ or the currentQuestion. The answer of every question will be stored in the array answers. So, we will loop the answers with the help of ‘v-for’ and display every answer as the button element. With that, v-html=”answer” will display answer on the button. The logic will be executed by handleClick that we will see later in the script part. Here’s the logic part of the Quiz component. Let’s pick a method one at a time and see what the logic is about.
Fetch Questions The prop ‘questions’ is intialized with an empty array. When the ‘loading’ is true, using Trivia API, we will fetch the questions and when the component will mount we will push them to the array. Here, five questions will be fetched every time an API call is made.
async fetchQuestions() { this.loading = true; //fetching questions from API let response = await fetch( "https://opentdb.com/api.php? amount=5&category=21&type=multipl e" ); let index = 0; //To identify single answer let data = await response.json(); let questions = data.results.map((question) => { question.answers = [ question.correct_answer, ...question.incorrect_answers, ];
//shuffle above array for (let i = question.answers.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [question.answers[i], question.answers[j]] = [ question.answers[j], question.answers[i], ]; } //add right answers and key question.rightAnswer = null; question.key = index; index++; return question; }); this.questions = questions; this.loading = false; },
Display Current Question The computed property currentQuestion() will return the current question at the current index.
currentQuestion() { if (this.questions !== []) { return this.questions[this.index]; } return null; },
Count Correct Answers The below code snippet is to keep count of the correct answers. correctAnswers() { if (this.questions && this.questions.length > 0) { let streakCounter = 0; this.questions.forEach(function (question) { if (!question.rightAnswer) { return; } else if (question.rightAnswer === true) { streakCounter++; } });
return streakCounter; } else { return "--"; } },
Calculate score The below logic will calculate score. The ‘score()’ will use a reducer array prototype to reduce the current questions array to a n number. It returns the ‘score’ object that we use in the customModal component. score() { if (this.questions !== []) { return { allQuestions: this.questions.length, answeredQuestions: this.questions.reduce((count, currentQuestion) => { if (currentQuestion.userAnswer) {
// userAnswer is set when user has answered a question, no matter if right or wrong count++; } return count; }, 0), correctlyAnsweredQuestions: this.questions.reduce( (count, currentQuestion) => { if (currentQuestion.rightAnswer) { // rightAnswer is true, if user answered correctly count++; } return count; }, 0 ), };
} else { return { allQuestions: 0, answeredQuestions: 0, correctlyAnsweredQuestions: 0, }; } },
Watcher on Quiz Completion We will keep watcher on quizCompleted() and if the quiz is completed, it will emit the event and display the score using this.score to App component. watch: { quizCompleted(completed) { completed && setTimeout(() => { this.$emit("quiz-completed", this.score); }, 3000); }, },
Check Correct Answer To check correct answer. For that, it will compare userAnswer, answer given by user, and correct_answer, answer given by API. It further sets ‘.rightAnswer’ and ‘.wrongAnswer’ accordingly and manages the index state for moving on to the next question. checkCorrectAnswer(e, index) { let question = this.questions[index]; if (question.userAnswer) { if (this.index < this.questions.length - 1) { setTimeout( function () { this.index += 1; }.bind(this), 3000 ); }
if (question.userAnswer === question.correct_answer) { /* Set class on Button if user answered right, to celebrate right answer with animation joyfulButton */ e.target.classList.add("rightAnswer"); /* Set rightAnswer on question to true, computed property can track a streak out of 20 questions */ this.questions[index].rightAnswer = true; } else { /* Mark users answer as wrong answer */ e.target.classList.add("wrongAnswer"); this.questions[index].rightAnswer = false;
/* Show right Answer */ let correctAnswer = this.questions[index].correct_answer; let allButtons = document.querySelectorAll(`[index="${inde x}"]`); allButtons.forEach(function (button) { if (button.innerHTML === correctAnswer) { button.classList.add("showRightAnswer"); } }); } } },
Run the server
After running the server, hit the browser and your UI will look something like this
On clicking the answer you will know whether your answer is correct or not and simultaneously display next question. At the end of the quiz you will have the score board that will display your correct answer(s).
Github Repository: VueJS Quiz App
Feel free to visit the github source code: VueJS Quiz App and clone the repository to play around with the code.
Conclusion
So, this was about how to develop frontend Quiz app using VueJS. Are you a keen learner for VueJS? If yes, then VueJS tutorials page is for you! Visit different tutorials and start diving deep in advanced VueJS knowledge or polish your fundamentals for VueJS as well.
Thank You
www.bacancytechnology.com