0

I have the following radio buttons values to be counted using JS function and gives score in the bottom, but I get the following error "Uncaught TypeError: radioElems.forEach is not a function at HTMLDocument.":

    <div class="data">
    <label>Assis<span class="red_star">*</span></label>
    <span><input type="radio" class="radio" name="Assis" value="0" required> 0</span>
    <span><input type="radio" class="radio" name="Assis" value="1" required> 1</span>
    <span><input type="radio" class="radio" name="Assis" value="2" required> 2</span>
    <span><input type="radio" class="radio" name="Assis" value="3" required> 3</span>
    </div>
    
    <div class="data">
    <label>En train<span class="red_star">*</span></label>
    <span><input type="radio" class="radio" name="En_train" value="0" required> 0</span>
    <span><input type="radio" class="radio" name="En_train" value="1" required> 1</span>
    <span><input type="radio" class="radio" name="En_train" value="2" required> 2</span>
    <span><input type="radio" class="radio" name="En_train" value="3" required> 3</span>
    </div>

    <div class="score"><span>Score: </span><span id="resultScore">0</span></div>

//Javascript
    document.addEventListener( 'DOMContentLoaded', event => {
    const text = document.getElementById('resultScore')
    const radioElems = document.getElementsByClassName('radio')
    radioElems.forEach((radioElem) => { radioElem.addEventListener('change', () => {
      count()
    }) })
    const count = () => {
      let score = 0
      document.getElementsByClassName('["radio"]:checked').forEach(radioChecked => {
        score += parseInt(radioChecked.value, 10)
        text.innerHTML = score
      })
    }
  })
<div class="data">
<label>Assis en train de lire<span class="red_star">*</span></label>
<span><input type="radio" class="radio" name="Assis" value="0" required> 0</span>
<span><input type="radio" class="radio" name="Assis" value="1" required> 1</span>
<span><input type="radio" class="radio" name="Assis" value="2" required> 2</span>
<span><input type="radio" class="radio" name="Assis" value="3" required> 3</span>
</div>

<div class="data">
<label>En train de regarder la télévision<span class="red_star">*</span></label>
<span><input type="radio" class="radio" name="En_train" value="0" required> 0</span>
<span><input type="radio" class="radio" name="En_train" value="1" required> 1</span>
<span><input type="radio" class="radio" name="En_train" value="2" required> 2</span>
<span><input type="radio" class="radio" name="En_train" value="3" required> 3</span>
</div>

<div class="score"><span>Score: </span><span id="resultScore">0</span></div>
Isabella
  • 137
  • 12
  • 2
    `HTMLCollection`s don’t have a `forEach` method. – Sebastian Simon Aug 23 '21 at 12:09
  • 1
    [Duplicate](//google.com/search?q=site%3Astackoverflow.com+js+getElementsByClassName+forEach) of [JS: iterating over result of getElementsByClassName using Array.forEach](/q/3871547/4642212). – Sebastian Simon Aug 23 '21 at 12:09
  • @SebastianSimon I am lost! – Isabella Aug 23 '21 at 12:36
  • 1
    Why? Use [event delegation](//developer.mozilla.org/docs/Learn/JavaScript/Building_blocks/Events#Event_delegation) instead of assigning multiple event listeners — it’s more maintainable, and applies to dynamically added elements. E.g., use an [event argument](//developer.mozilla.org/docs/Web/API/EventTarget/addEventListener#The_event_listener_callback)’s [`target`](//developer.mozilla.org/docs/Web/API/Event/target). See [the tag info](/tags/event-delegation/info) and [What is DOM Event delegation?](/q/1687296/4642212). – Sebastian Simon Aug 23 '21 at 12:37
  • @SebastianSimon can you demonstrate a snippets? thank you. – Isabella Aug 23 '21 at 12:47

1 Answers1

1

I changed the getElementsByClassName to querySelectorAll. querySelectorAll has the function forEach:

//Javascript
var text;

const count = () => {
  let score = 0
  document.querySelectorAll('input[class = "radio"]:checked').forEach(radioChecked => {
    score += parseInt(radioChecked.value, 10);
  });
  text.innerHTML = score;
};

document.addEventListener('DOMContentLoaded', event => {
  text = document.getElementById('resultScore');
  const radioElems = document.querySelectorAll('input[class = "radio"]');
  radioElems.forEach((radioElem) => {
    radioElem.addEventListener('change', () => {
      count();
    })
  })
});
<div class="data">
  <label>Assis en train de lire<span class="red_star">*</span></label>
  <span><input type="radio" class="radio" name="Assis" value="0" required> 0</span>
  <span><input type="radio" class="radio" name="Assis" value="1" required> 1</span>
  <span><input type="radio" class="radio" name="Assis" value="2" required> 2</span>
  <span><input type="radio" class="radio" name="Assis" value="3" required> 3</span>
</div>

<div class="data">
  <label>En train de regarder la télévision<span class="red_star">*</span></label>
  <span><input type="radio" class="radio" name="En_train" value="0" required> 0</span>
  <span><input type="radio" class="radio" name="En_train" value="1" required> 1</span>
  <span><input type="radio" class="radio" name="En_train" value="2" required> 2</span>
  <span><input type="radio" class="radio" name="En_train" value="3" required> 3</span>
</div>

<div class="score"><span>Score: </span><span id="resultScore">0</span></div>
chrwahl
  • 8,675
  • 2
  • 20
  • 30
  • Using input[type = "radio"] makes conflict with other radio buttons group in the page, this is why I am trying to use getEementsByClassName to target this specific radio group with class name "radio" :) – Isabella Aug 23 '21 at 12:55
  • 1
    @Isabella ok, now I updated the selectors, selecting for class name. Just because I'm using querySelectorAll doesn't mean that I cannot select for class names. The code is solving the issue with forEach. To make it work for your particular case is up to you. – chrwahl Aug 23 '21 at 13:49