Implementing a Mobile Assessment Quiz with AngularJS

Core Functionality and Requirements

  1. Up on selecting an answer, its background changes to yellow (selected state) and the interface automatically avdances to the next question.
  2. The progress indicator at the top updates when moving to the next question.
  3. The selected answer's corresponding score is recorded for final result calculation.
  4. Users can swipe right to review previous questions.
  5. Navigation to the next question is disabled if the current question is unanswered.
  6. Upon completing the final question, the assessment result page is displayed.

Data Structure

The quiz questions and answers are defined in a JSON structure. Each question contains a list of possible enswers, each with associated text, score value, and order.

{
  "Questions": [
    {
      "Question": "Your Age Range:",
      "AnswerList": [
        {"Text": "Under 30", "Score": 5, "OrderNo": 0},
        {"Text": "30-39", "Score": 4, "OrderNo": 1},
        {"Text": "40-49", "Score": 3, "OrderNo": 2},
        {"Text": "50-59", "Score": 2, "OrderNo": 3},
        {"Text": "Over 60", "Score": 1, "OrderNo": 4}
      ]
    }
  ]
}

HTML Structure

<div ng-controller="QuizController as ctrl">
  <div class="progress-container">
    <ul>
      <li ng-repeat="q in ctrl.questions track by $index">
        <span class="step">{{$index + 1}}</span>
      </li>
    </ul>
    <div class="progress-info">Completed {{ctrl.currentStep}}/{{ctrl.totalQuestions}}</div>
  </div>
  <ul class="questions-list" id="questionsContainer">
    <li ng-repeat="question in ctrl.questions track by $index" class="question-slide">
      <div class="question-text">{{$index + 1}}. {{question.Question}}</div>
      <ul class="answers">
        <li ng-repeat="answer in question.AnswerList"
            ng-click="ctrl.selectAnswer(answer, $parent.$index)"
            ng-class="{'selected': answer.isSelected}">
          {{ctrl.optionLabels[$index]}}. {{answer.Text}}
        </li>
      </ul>
    </li>
  </ul>
  <div ng-show="ctrl.showResults">
    <span>Total Score: {{ctrl.totalScore}}</span>
  </div>
</div>

Controller Implementation

angular.module('quizApp', [])
  .controller('QuizController', ['$scope', '$http', function($scope, $http) {
    var self = this;
    self.optionLabels = ['A', 'B', 'C', 'D', 'E'];
    self.questions = [];
    self.totalScore = 0;
    self.showResults = false;
    self.currentStep = 0;
    self.totalQuestions = 0;

    // Load question data
    $http.get('/api/questions').then(function(response) {
      self.questions = response.data.Questions;
      self.totalQuestions = self.questions.length;
    });

    // Handle answer selection
    self.selectAnswer = function(chosenAnswer, questionIndex) {
      var currentQuestion = self.questions[questionIndex];
      
      // Deselect all answers for this question
      currentQuestion.AnswerList.forEach(function(ans) {
        ans.isSelected = false;
      });
      
      // Select the clicked answer
      chosenAnswer.isSelected = true;
      
      // Move to next question if available
      if (questionIndex < self.totalQuestions - 1) {
        self.navigateToQuestion(questionIndex + 1);
      } else {
        self.calculateFinalScore();
        self.showResults = true;
      }
      
      self.updateProgress();
    };

    self.navigateToQuestion = function(targetIndex) {
      // Implementation for smooth transition between questions
    };

    self.calculateFinalScore = function() {
      self.totalScore = self.questions.reduce(function(sum, q) {
        var selected = q.AnswerList.find(function(ans) {
          return ans.isSelected;
        });
        return sum + (selected ? selected.Score : 0);
      }, 0);
    };

    self.updateProgress = function() {
      self.currentStep = self.questions.filter(function(q) {
        return q.AnswerList.some(function(ans) {
          return ans.isSelected;
        });
      }).length;
    };

    // Touch event handlers for swipe navigation
    var touchStartX = 0;
    var touchThreshold = 50;
    
    document.getElementById('questionsContainer').addEventListener('touchstart', function(e) {
      touchStartX = e.touches[0].clientX;
    });
    
    document.getElementById('questionsContainer').addEventListener('touchend', function(e) {
      var touchEndX = e.changedTouches[0].clientX;
      var deltaX = touchEndX - touchStartX;
      
      if (Math.abs(deltaX) > touchThreshold) {
        if (deltaX > 0 && self.currentStep > 0) {
          // Swipe right - go to previous question
          self.navigateToQuestion(self.currentStep - 1);
        } else if (deltaX < 0 && self.currentStep < self.totalQuestions - 1) {
          // Swipe left - go to next question
          self.navigateToQuestion(self.currentStep + 1);
        }
      }
    });
  }]);

Key CSS Styles

.question-slide {
  position: absolute;
  width: 100%;
  transition: transform 0.3s ease;
  transform: translate3d(100%, 0, 0);
}

.question-slide.active {
  transform: translate3d(0, 0, 0);
}

.answers li.selected {
  background-color: #ffeb3b;
}

.step {
  display: inline-block;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  background-color: #e0e0e0;
  text-align: center;
  line-height: 30px;
}

.step.completed {
  background-color: #4caf50;
  color: white;
}

Tags: AngularJS Mobile Development javascript Quiz Application Touch Events

Posted on Thu, 20 Aug 2026 16:53:51 +0000 by rstrik