Michael Bade
Michael Bade

Reputation: 25

JS event is firing when DOM is loaded

I'm designing a quiz app for fun. The quiz will show one question, and it's four options to answer. I'm using vanilla JS to update the DOM, and need to add an eventListener for each answer that is rendered. For some reason, the eventListener is firing as soon as the DOM is rendered. Any ideas as to why?

  //add each answer to the answerContainer
  answerContainer.innerHTML = '';
  for (let i = 0; i < allAnswersFlattened.length; i++) {
    let individualAnswer = document.createElement('div');
    individualAnswer.className = 'answer';
    let answerText = document.createTextNode(allAnswersFlattened[i]);
    individualAnswer.appendChild(answerText);
    individualAnswer.addEventListener("click", checkForAnswer(i, allAnswersFlattened));
    answerContainer.appendChild(individualAnswer);
  }

Upvotes: 0

Views: 44

Answers (2)

Nikita Chayka
Nikita Chayka

Reputation: 2137

Your event is firing because you call the function here:

individualAnswer.addEventListener("click", checkForAnswer(i, allAnswersFlattened));

checkForAnswer(i, allAnswersFlattened) - executes the funtion, not passes it as argument to addEventListener

What you need to do is to create an event handler from which you would call your "checkForAnswer" (see below myEventListener):

answerContainer.innerHTML = '';
for (let i = 0; i < allAnswersFlattened.length; i++) {
  var myEventListener = function(e) {
    checkForAnswer(i, allAnswersFlattened)
  };
  let individualAnswer = document.createElement('div');
  individualAnswer.className = 'answer';
  let answerText = document.createTextNode(allAnswersFlattened[i]);
  individualAnswer.appendChild(answerText);
  individualAnswer.addEventListener("click", myEventListener );
  answerContainer.appendChild(individualAnswer);
}

Upvotes: 0

dave
dave

Reputation: 64657

You need to do it like this:

individualAnswer.addEventListener("click", function() {
    checkForAnswer(i, allAnswersFlattened));
});

but then you will get issues where i won't be right (since by the time it is clicked, the i value has been incremented.

So probably you should do:

individualAnswer.addEventListener("click", ((i) => function() {
    checkForAnswer(i, allAnswersFlattened));
})(i));

or

individualAnswer.addEventListener("click", checkForAnswer.bind(this, i, allAnswersFlattened));

or have checkForAnswer return a function:

function checkForAnswer(i, allAnswers) => () => {
    // whatever the code was before
}

Upvotes: 2

Related Questions