0

I am trying to add my own spin on a AngularJS tutorial I did about a Saturn Quiz by changing it from multiple choice to a fill-in-the-blank quiz.

I am able to get the first answer to recognize if it is right or wrong but the next question always returns incorrect even when the answer is right. By using console.log I find that the input value though changed is not recognized by AngularJS. It always retains the first value I put into the quiz.

Plunkr Demo

HTML

<div id="myQuiz" ng-controller="QuizController">
    <h1>Test Your Knowledge:<span>Saturn</span></h1>
    <div class="progress">  
        <div class="{{ ($index === activeQuestion) ? 'on' : 'off' }} 
            {{ (myQuestion.questionState === 'answered') ? 'answered' : 'unanswered' }}
            {{ (myQuestion.correctness === 'correct') ? 'correct' : 'incorrect' }}" 
            ng-repeat="myQuestion in myQuestions">
        </div>
    </div>

    <div class="intro {{ (activeQuestion > -1) ? 'inactive' : 'active' }}"> 
        <h2>Welcome</h2>
        <p>Click to begin to test your knowledge of Saturn.</p>
        <p class="btn" ng-click="activeQuestion = 0">Begin</p>
    </div>

    <div class="question
        {{ $index === activeQuestion ? 'active' : 'inactive' }}
        {{ myQuestion.questionState === 'answered' ? 'answered' : 'unanswered' }}" 
        ng-repeat="myQuestion in myQuestions">
        <p class="txt"> {{ myQuestion.instructions }} </p>
        <div class="txt" ng-bind-html="myQuestion.question | trustAsHtml">
        </div>  

        <p class="ans" 
            ng-class="{  
                correct:isCorrect($index, $index)}"
            ng-click="checkAnswer($index, $index)">Check Answer 
        </p>

        <div class="feedback">
            <p ng-show="myQuestion.correctness === 'correct'"><strong>Correct</strong>.</p>
            <p ng-show="myQuestion.correctness === 'incorrect'">Oops! That is not correct.</p>
            <p> {{ myQuestion.feedback }} </p>
            <div class="btn" ng-click="selectContinue()">Continue</div>
        </div>
</div>

App.js

    (function(){
    var codeApp = angular.module('codeApp', ['ngSanitize']);

    codeApp.controller('QuizController', ['$scope', '$http', "$sce", function($scope, $http, $sce){
        $scope.score = 0;
        $scope.activeQuestion = -1;
        $scope.activeQuestionAnswered = 0;
        $scope.percentage = 0;

        $http.get('quiz_data.json').then(function(quizData){
            $scope.myQuestions = quizData.data;
            $scope.totalQuestions = $scope.myQuestions.length;
        });
        $scope.checkAnswer = function(qIndex,aIndex){
            var questionState = $scope.myQuestions[qIndex].questionState;

                if(questionState != 'answered') {
                    var userAnswer = document.getElementsByClassName("fillin")[0].value;
                    var correctAnswer = $scope.myQuestions[qIndex].questionAnswer;

                    $scope.myQuestions[qIndex].questionAnswer = correctAnswer;

                            if(userAnswer === correctAnswer){
                                $scope.myQuestions[qIndex].correctness = 'correct';
                                $scope.score += 1;
                                console.log('Correct!' + $scope.score);
                            }
                            else{
                                $scope.myQuestions[qIndex].correctness = 'incorrect';
                                console.log('Wrong!');
                                console.log(correctAnswer);
                                console.log(userAnswer);
                                console.log( document.getElementsByClassName("fillin")[0].value );
                            }
                        $scope.myQuestions[qIndex].questionState = 'answered';

                }else{
                    console.log('Something is wrong');
                }

        }

        $scope.selectContinue = function(){
            return $scope.activeQuestion += 1;

        }

        $scope.createShareLinks = function(percentage){

            var url = 'http://codifydesign.com';
            var emailLink = '<input type="text" placeholder="hi" /><a class="btn email" href="mailto:?subject=Try to beat my quiz score!&amp;body=I scored a '+percentage+'% on this quiz about Saturn. Try to beat my score at '+url+'">Email a friend</a>';
            var twitterLink = '<a class="btn twitter" target="_blank" href="http://twitter.com/share?text=I scored a '+percentage+'% on this quiz about Saturn. Try to beat my score at&amp;hashtags=SaturnQuiz&amp;url='+url+'">Tweet your score</a>';
            var newMarkup = emailLink + twitterLink;
            return $sce.trustAsHtml(newMarkup);
        }
    }]).filter('trustAsHtml', [
    '$sce',
    function($sce) {
        return function(value) {
            return $sce.trustAsHtml(value);
        }
    }
    ]);
})();

data.json

[
    {
        "questionId": 0,
        "question" : "Saturn is <input id='guess-input' class='fillin' ng-blur='clearValues()' type='text' name='\"six\"'> many planets from the sun?",
        "questionAnswer" : "six"
    },
    {
        "questionId": 1,
        "question" : "Around Saturn are <input id='guess-input' class='fillin' ng-blur='clearValues()' type='text' name='\"rings\"'>",
        "questionAnswer" : "rings"
    }
]
2
  • With the AngularJS framework, the use of getElementsByClassName is a code smell, a symptom of a deeper problem. The AngularJS framework interacts with the <input> element using the ng-model directive. For more information, see AngularJS <input> Directive API Reference. Commented Jun 14, 2018 at 21:07
  • @georgeawg Thank you for bringing this to my attention! I will leave the question open a little longer if you would like to answer since you seem knowledgeable about AngularJS. I have used ng-model in another tutorial and I will look into it more to understand how it works and how I can apply it here. Commented Jun 14, 2018 at 21:33

1 Answer 1

1

You have hardcoded it to always look for the first instance of an element with a class of fillin. Change both instances of this...

document.getElementsByClassName("fillin")[0].value

...to this...

document.getElementsByClassName("fillin")[aIndex].value

...and it should begin working for you.

Sign up to request clarification or add additional context in comments.

1 Comment

This is really helpful. Following the tutorial a couple of times I kind of understood the concept of the qIndex and aIndex but I am not sure where they are really pulling from (or how). This solution works, and it makes sense to me on a JS level!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.