Search code examples
javascriptperformancedomevent-handlingevent-delegation

How to add event delegation to "change" event (not click) on radio buttons?


I often times easily implemented event delegation with the "click" event on parent elements of something with code like

HTML:

<div>
  <span>
    <input
      type="radio"
      id="all0"
      name="difficulty-ask"
      class="difficultyaskclass"
      value="all"
      checked="checked"
    />
    <label for="all0">All</label>
    <input
      type="radio"
      id="2easy1"
      name="difficulty-ask"
      class="difficultyaskclass"
      value="easy"
    />
    <label for="2easy1">Easy</label>
    <input
      type="radio"
      id="2med2"
      name="difficulty-ask"
      class="difficultyaskclass"
      value="medium"
    />
    <label for="2med2">Medium</label>
    <input
      type="radio"
      id="2hard3"
      name="difficulty-ask"
      class="difficultyaskclass"
      value="hard"
    />
    <label for="2hard3">Hard</label>
  </span>
</div>

JS:

parentelement.addEventlistener('click', (event) => {
if(event.target.classList.contains('targetelement'){Code..}};

(parentelement is just a regular div, in which the radio buttons are placed)

How does it work now with the 'change' event for example for radio buttons if they switch state?

I made it work first by just looping through all of them and then add an eventListener to each. But this is obviously not the desired solution, i definitely need some event delegation there.


Solution

  • you may use input event, which is also valid for any forms elements

    demo:

    const myForm = document.forms['my-form'];
      
    myForm.addEventListener('submit', e => 
      {
      e.preventDefault(); // disable submit - page reload
      const formValues = Object.fromEntries(new FormData(myForm).entries());
      console.log( formValues );
      setTimeout(console.clear,3000);
      })
    
    myForm.addEventListener('input', e => 
      {
      if (!e.target.matches('input[type="radio"]')) return;
      
      console.log(myForm['difficulty-ask'].value);
      setTimeout(console.clear,1300);
      });
    label    { display: block; cursor: pointer; }
    fieldset { width: fit-content; }
    <form name="my-form">
      <fieldset>
        <legend> difficulty </legend>
        <label>
          <input name="difficulty-ask" type="radio" value="all" checked >
          All
        </label>
        <label>
          <input name="difficulty-ask" type="radio" value="easy" >
          Easy
        </label>
        <label>
          <input name="difficulty-ask" type="radio" value="medium" >
          Medium
        </label>
        <label>
          <input name="difficulty-ask" type="radio" value="hard" >
          Hard
        </label>
      </fieldset>
      <button>submit</button>
    </form>