Why is the 'question' varaible inside loadQuiz() null?

Viewed 39

I am trying to make a simple quiz app. The 'question' variable inside the 'loadQuiz()' function comes out to be null . Why is it so ?

The 'question' id is given in the HTML tag and I am trying to manipulate its inner text to the questions mentioned in the quizdata array of JavaScript.

Here is the console output: ''' Uncaught TypeError: question is null '''

var quizdata= [
    {
        question:"Which framework is related to JS ?",
        a:'.net',
        b:'Flask',
        c:'React',
        d:'Django',
        correct: 'c'
    },
    {
        question:"Which is not a programming language ?",
        a:'HTML',
        b:'Python',
        c:'Java',
        d:'JavaScript',
        correct: 'a'
    },
    {
        question:"Which is not a framework ?",
        a:'React',
        b:'JavaScript',
        c:'Angular',
        d:'Django',
        correct: 'b'
    },
    {
        question:"CSS stands for - ",
        a:'Cascading Style State',
        b:'Cascading Style Sheet',
        c:'Cascading Sheet of Style',
        d:'None of the above',
        correct: 'b'
    }
]

var quiz = document.getElementById('quiz')
var answer = document.querySelectorAll('.answer')
var question = document.getElementById('question')
var option_a=document.getElementById ('a_value')
var option_b=document.getElementById ('b_value')
var option_c=document.getElementById ('c_value')
var option_d=document.getElementById ('d_value')

var submitbtn=document.getElementById('submit')

var currentQuestion=0
var quizScore=0 



loadQuiz()

console.log(option_a)

function loadQuiz(){

    deselect()

    question.innerHTML= quizdata[currentQuestion].question
    option_a.innerText= quizdata[currentQuestion].a
    option_b.innerText= quizdata[currentQuestion].b
    option_c.innerText= quizdata[currentQuestion].c
    option_d.innerText= quizdata[currentQuestion].d

}

function deselect()
{
    answer.forEach(answer=>answer.checked=false)
}

submitbtn.addEventListener('click', ()=>{

    var selectedOption

    answer.forEach(answer=>{
        if(answer.checked)
        {
            selectedOption=answer.id
        }
    })

    if(selectedOption==quizdata[currentQuestion].correct)
    {
        quizScore+=1
    }
    currentQuestion+=1
    
    if(currentQuestion==quizdata.length)
    {
        document.getElementById('quizdiv').innerHTML='<h1>You have answered $(quizScore) correctly out of $(quizdata.length)</h1>'
    }
    else
    {
        loadQuiz()
    }
})
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Quiz</title>

    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0-beta1/dist/css/bootstrap.min.css" rel="stylesheet"
        integrity="sha384-0evHe/X+R7YkIZDRvuzKMRqM+OrBnVFBL6DOitfPri4tjfHxaWutUpFmBp4vmVor" crossorigin="anonymous">
    <link rel="stylesheet" href="style.css">
</head>

<body>
    <script src="index.js"></script>
    <div class="container">
        <div class="row justify-content-center">
            <div class="col-md-7 ">
                <h1 class="text-center">JS Quiz</h1>
                <hr class="rounded">
                <div id="quizdiv">
                    <h2 id="question"> Question </h2>
                    <hr class="dashed">
                    <li>
                        <!-- 'name' attribute is same in all the list elements so that only one radio box may be selected at a time. -->
                        <input type="radio" name="answer" id="a" class="answer">
                        <label for="a" id="a_value">option a</label>
                    </li>
                    <li>
                        <!-- 'name' attribute is same in all the list elements so that only one radio box may be selected at a time. -->
                        <input type="radio" name="answer" id="b" class="answer">
                        <label for="b" id="b_value">option b</label>
                    </li>
                    <li>
                        <!-- 'name' attribute is same in all the list elements so that only one radio box may be selected at a time. -->
                        <input type="radio" name="answer" id="c" class="answer">
                        <label for="c" id="c_value">option c</label>
                    </li>
                    <li>
                        <!-- 'name' attribute is same in all the list elements so that only one radio box may be selected at a time. -->
                        <input type="radio" name="answer" id="d" class="answer">
                        <label for="d" id="d_value">option d</label>
                    </li>

                    <button class="btn btn-primary" id="submit">SUBMIT</button>

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

</body>

</html>

Any help would be appreciated. Thanks in advance.

1 Answers

As user1599011 already stated, the <script> tag is loading before the DOM is loaded so question will be null since it doesn't exist yet. Can't reproduce the problem stated in question of course, but I did fix the last part:

Change this string...

'<h1>You have answered $(quizScore) correctly out of $(quizdata.length)</h1>'

...to a template literal:

`<h1>You have answered ${quizScore} correctly out of ${quizdata.length}</h1>`

The string in the first code block is syntactically incorrect, $() is usually jQuery syntax -- I think you were thinking of template literal interpolation with this syntax ${}. Also, template literals are wrapped in grave marks `` not single ' or double " quotes -- on a QUERTY keyboard the `~ key is located at the upper left-hand corner.

var quizdata = [{
    question: "Which framework is related to JS ?",
    a: '.net',
    b: 'Flask',
    c: 'React',
    d: 'Django',
    correct: 'c'
  },
  {
    question: "Which is not a programming language ?",
    a: 'HTML',
    b: 'Python',
    c: 'Java',
    d: 'JavaScript',
    correct: 'a'
  },
  {
    question: "Which is not a framework ?",
    a: 'React',
    b: 'JavaScript',
    c: 'Angular',
    d: 'Django',
    correct: 'b'
  },
  {
    question: "CSS stands for - ",
    a: 'Cascading Style State',
    b: 'Cascading Style Sheet',
    c: 'Cascading Sheet of Style',
    d: 'None of the above',
    correct: 'b'
  }
]

var quiz = document.getElementById('quiz')
var answer = document.querySelectorAll('.answer')
var question = document.getElementById('question')
var option_a = document.getElementById('a_value')
var option_b = document.getElementById('b_value')
var option_c = document.getElementById('c_value')
var option_d = document.getElementById('d_value')

var submitbtn = document.getElementById('submit')

var currentQuestion = 0
var quizScore = 0



loadQuiz()

console.log(option_a)

function loadQuiz() {

  deselect()

  question.innerHTML = quizdata[currentQuestion].question
  option_a.innerText = quizdata[currentQuestion].a
  option_b.innerText = quizdata[currentQuestion].b
  option_c.innerText = quizdata[currentQuestion].c
  option_d.innerText = quizdata[currentQuestion].d

}

function deselect() {
  answer.forEach(answer => answer.checked = false)
}

submitbtn.addEventListener('click', () => {

  var selectedOption

  answer.forEach(answer => {
    if (answer.checked) {
      selectedOption = answer.id
    }
  })

  if (selectedOption == quizdata[currentQuestion].correct) {
    quizScore += 1
  }
  currentQuestion += 1

  if (currentQuestion == quizdata.length) {
    document.getElementById('quizdiv').innerHTML = `<h1>You have answered ${quizScore} correctly out of ${quizdata.length}</h1>`
  } else {
    loadQuiz()
  }
})
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Quiz</title>

  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0-beta1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-0evHe/X+R7YkIZDRvuzKMRqM+OrBnVFBL6DOitfPri4tjfHxaWutUpFmBp4vmVor" crossorigin="anonymous">
  <link rel="stylesheet" href="style.css">
</head>

<body>
  
  <div class="container">
    <div class="row justify-content-center">
      <div class="col-md-7 ">
        <h1 class="text-center">JS Quiz</h1>
        <hr class="rounded">
        <div id="quizdiv">
          <h2 id="question"> Question </h2>
          <hr class="dashed">
          <li>
            <!-- 'name' attribute is same in all the list elements so that only one radio box may be selected at a time. -->
            <input type="radio" name="answer" id="a" class="answer">
            <label for="a" id="a_value">option a</label>
          </li>
          <li>
            <!-- 'name' attribute is same in all the list elements so that only one radio box may be selected at a time. -->
            <input type="radio" name="answer" id="b" class="answer">
            <label for="b" id="b_value">option b</label>
          </li>
          <li>
            <!-- 'name' attribute is same in all the list elements so that only one radio box may be selected at a time. -->
            <input type="radio" name="answer" id="c" class="answer">
            <label for="c" id="c_value">option c</label>
          </li>
          <li>
            <!-- 'name' attribute is same in all the list elements so that only one radio box may be selected at a time. -->
            <input type="radio" name="answer" id="d" class="answer">
            <label for="d" id="d_value">option d</label>
          </li>

          <button class="btn btn-primary" id="submit">SUBMIT</button>

        </div>
      </div>
    </div>
  </div>
<script src="index.js"></script>
</body>

</html>

Related