Guide 3.9: Real Projects

Build the Answer System

When a user clicks on an option (e.g., Option B), we need to record that choice in our userAnswers dictionary. We also need to instantly update the UI (like turning the number grid button green) so they know the answer was saved.

Event Delegation

3.9.1

Because our radio buttons are destroyed and recreated every time the user navigates to a new question, we cannot attach event listeners directly to the inputs. We must use Event Delegation by attaching a listener to the parent container.

const optionsContainer = document.getElementById('optionsContainer');

optionsContainer.addEventListener('change', (e) => {
  // Ensure the triggered event came from a radio button
  if (e.target.name === 'exam_option') {
    const selectedValue = e.target.value; // 'a', 'b', 'c', or 'd'
    
    // Save to our global state dictionary using the question index as the key
    userAnswers[currentQuestionIndex] = selectedValue;
    
    // Re-render the grid to turn this question's button green
    updateGridColors();
  }
});

Extracting the Grid Update Logic

3.9.2

Let's refactor the color logic we wrote earlier into a separate function so we can call it whenever an answer is selected without re-rendering the entire question text.

function updateGridColors() {
  const allNavBtns = document.querySelectorAll('.nav-num-btn');
  
  allNavBtns.forEach((btn, idx) => {
    if (idx === currentQuestionIndex) {
      btn.style.background = '#007bff'; // Active
      btn.style.color = 'white';
    } else if (userAnswers[idx]) {
      btn.style.background = '#28a745'; // Answered (Green)
      btn.style.color = 'white';
    } else {
      btn.style.background = '#eee'; // Unanswered
      btn.style.color = '#333';
    }
  });
}

Time's up!

Next, we will calculate the final score when the user clicks Submit Exam.

Next Guide: Calculate the Score →
Avatar

How can we help?

We reply immediately

Hello! 👋 How can we help you today?