0

I've been practicing AngularJS1x doing tutorials from Lynda and Udemy. I did a tutorial that created a multiple choice quiz. I wanted to see if I understood the code by recreating it and then push it farther but trying to make it a fill in the blank quiz.

The questions and answers all pull from a JSON file. The fill-in check works correctly and if the user input matches the string in the JSON object it works fine. I didn't change much but the code does not work when trying to call the $parent.index array. For reference of the original code I used as a multiple choice quiz you can find that link here

I would love it if someone could also explain why I was wrong if I set it up incorrectly so I can get better. I compared it to the original code and could not find where I went wrong.

The problem lies when targeting the array number of the object. I will also show the code below.

Problem It lies within anything that calls the qIndex parameter like this:

$scope.myQuestions[qIndex].questionState; //Says it is undefined

if I give it a hard coded array number like 0 it works

$scope.myQuestions[0].questionState //If all of them are like this its fine as it calls the first question and finds the correct answer if typed into the input.

Here is the code below:

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($parent.$index, $index)}"
                ng-click="checkAnswer($parent.$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 class="results {{ (totalQuestions === activeQuestion) ? 'active' : 'inactive' }}">
            <div>
                <h3>Results</h3>

                <p>You Scored {{percentage}}% by correctly answering {{score}} of the total {{totalQuestions}} questions.</p>
                <p>Use the links below to challenge your friends.</p>

                <div class="share" ng-bind-html="createShareLinks(percentage)"></div>

            </div>
        </div>
    </div>

QUIZ.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 = $(".fillin").val();
                    console.log(aIndex); //logs 0
                    console.log(qIndex); //logs undefined

                    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!');
                            }
                        $scope.myQuestions[qIndex].questionState = 'answered';

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

                $scope.isCorrect = function(qIndex,aIndex){
                    return $scope.myQuestions[qIndex].questionAnswer === userAnswer;
                }
        }

        $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);
        }
    }
    ]);
})();

JSON

[
    {
        "questionId": 0,
        "question" : "Saturn is <input id='guess-input' class='fillin' type='text' name='\"six\"'> many planets from the sun?",
        "questionAnswer" : "six"
    },
    {
        "questionId": 1,
        "question" : "Around Saturn are <input id='guess-input' class='fillin' type='text' name='\"rings\"'>",
        "questionAnswer" : "rings"
    }
]

1 Answer 1

1

In angularjs $parent.$index is $index from the parent scope. It is useful when you have nested loops. Then you can get $index from the parent scope using $parent.$index construction. You code doesn't have nested loops. ng-repeat="myQuestion in myQuestions" is top levele loop. So it doesn't have index in its parent scope. I can guess that in original code there was one loop in another like one ng-repeat in another ng-repeat.

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

Comments

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.