Skip to Content
Course content

181: Building a Simple Quiz Application

Click on the "Edit" button in the top corner of the screen to edit your slide content.

By now, you've got the hang of manipulating the DOM and handling events. But the real magic happens when you combine those skills to manage state—keeping track of where the user is in a process and reacting to their input. Today, we're going to build a simple JavaScript Trivia Quiz. It's a classic project because it forces you to think about how data (your questions) transforms into a UI (the buttons and text the user sees).

Mapping out our quiz data

Before touching any HTML, I always start with the data. If we hard-code every question into the HTML, we're making a maintenance nightmare for ourselves. Instead, I'll use an array of objects. Each object represents a single question, its options, and the correct answer key.

const quizData = [
    {
        question: "Which keyword is used to declare a block-scoped variable?",
        options: ["var", "let", "set", "define"],
        correct: 1 // Index of 'let'
    },
    {
        question: "What is the result of '2' + 2 in JavaScript?",
        options: ["4", "22", "NaN", "Error"],
        correct: 1 // Index of '22'
    },
    {
        question: "Which method is used to add an element to the end of an array?",
        options: ["pop()", "shift()", "push()", "join()"],
        correct: 2 // Index of 'push()'
    }
];

I'm using the index of the correct answer rather than the string itself. Why? Because if I ever decide to change the wording of an answer, I don't have to hunt through my logic to update the "correct" value.

Getting the question onto the screen

Now we need a way to render this. I'll create a function called loadQuiz. This function needs to know which question we're currently on, so I'll keep a global variable currentQuizIndex. I'll grab the question text and the options array, then inject them into the DOM.

let currentQuizIndex = 0;
let score = 0;

function loadQuiz() {
    const currentData = quizData[currentQuizIndex];
    
    document.getElementById('question-text').innerText = currentData.question;
    
    const optionsContainer = document.getElementById('options-container');
    optionsContainer.innerHTML = ''; // Clear previous buttons

    currentData.options.forEach((option, index) => {
        const btn = document.createElement('button');
        btn.innerText = option;
        btn.onclick = () => handleAnswer(index);
        optionsContainer.appendChild(btn);
    });
}

Handling the user's choice (and fixing a rendering bug)

Here is where I usually trip up if I'm rushing. I wrote the handleAnswer function to check if the clicked index matched the correct index and then increment the currentQuizIndex. But when I first ran it, the quiz just... stopped. I realized I was incrementing the index but forgot to actually call loadQuiz() again to refresh the screen.

I also realized that if the user reaches the end of the array, quizData[currentQuizIndex] becomes undefined, and the whole app crashes. I need a guard clause to handle the end of the quiz.

function handleAnswer(selectedIndex) {
    if (selectedIndex === quizData[currentQuizIndex].correct) {
        score++;
    }

    currentQuizIndex++;

    if (currentQuizIndex < quizData.length) {
        loadQuiz(); // I forgot this the first time!
    } else {
        showResults();
    }
}

function showResults() {
    const container = document.getElementById('quiz-container');
    container.innerHTML = `<h2>You scored ${score}/${quizData.length}!</h2>`;
}

Putting the pieces together

To make this actually work, you'll need a basic HTML structure with an ID for the question and a container for the buttons. I prefer using a div for the options container so I can dynamically append buttons via JavaScript. This keeps the HTML clean and the logic centralized in the script.

The beauty of this approach is scalability. If you want to add 50 more questions, you don't touch the functions or the HTML; you just add more objects to your quizData array. That's the power of separating your data from your presentation.




📋 Practical Task

Exercise: Implementing a "Reset Quiz" Feature

Modify the showResults function from the lesson so that it doesn't just show the final score, but also provides a "Try Again" button. When this button is clicked, it should reset the score and currentQuizIndex to 0 and call loadQuiz() to restart the application without requiring the user to refresh the browser page.

Rating
0 0

There are no comments for now.

to be the first to leave a comment.