How to use on addEventListener on radio button in Plain Javascript?

Viewed 16767

How can i attach event listener on a radio button in my html? Considering this form:

<label>
    <input name="contract_duration" type="radio" value="6-Months" {{ $contract && $contract->contract_duration === '6-Months' ? 'checked' : ''  }} />
    <span>6-Months</span>
</label>

<label>
    <input name="contract_duration" type="radio" value="1-Year" {{ $contract && $contract->contract_duration === '1-Year' ? 'checked' : ''  }} />
    <span>1-Year</span>
</label>

<label>
    <input name="contract_duration" type="radio" value="2-Years" {{ $contract && $contract->contract_duration === '2-Years' ? 'checked' : ''  }} />
    <span>2-Years</span>
</label>

and this is my Javascript:

if(document.querySelector('input[name="contract_duration"]')){
    document.querySelector('input[name="contract_duration"]').addEventListener("click", function(){
        var item = document.querySelector('input[name="contract_duration"]').value;
        console.log(item);
    });
}

during execution, my codes only log the first one, which is the 6-Months others if click shows nothing.

3 Answers

The querySelector function only returns the first element of all the ones matched by the selector - hence your problem. You need to use querySelectorAll instead. This will return all the matched elements - and then you can loop through them to add an event listener to each.

Also, best practice in this scenario would be to listen to the "change" event rather than "click", then it doesn't fire unnecessarily when the user clicks an already-selected radio.

Demo:

if (document.querySelector('input[name="contract_duration"]')) {
  document.querySelectorAll('input[name="contract_duration"]').forEach((elem) => {
    elem.addEventListener("change", function(event) {
      var item = event.target.value;
      console.log(item);
    });
  });
}
<label>
    <input name="contract_duration" type="radio" value="6-Months" checked />
    <span>6-Months</span>
</label>

<label>
    <input name="contract_duration" type="radio" value="1-Year" />
    <span>1-Year</span>
</label>

<label>
    <input name="contract_duration" type="radio" value="2-Years" />
    <span>2-Years</span>
</label>

You need to use querySelectorAll instead, which returns a list of elements.

And the change event will run only for a chosen radio.

let contact = document.querySelectorAll('input[name="contract_duration"]');
                                  // or '.your_radio_class_name'

for (let i = 0; i < contact.length; i++) {
  contact[i].addEventListener("change", function() {
    let val = this.value; // this == the clicked radio,
    console.log(val);
  });
}
label {
  display: block;
}
<label>
  <input name="contract_duration" type="radio" value="6-Months"/>
  <span>6-Months</span>
</label>

<label>
  <input name="contract_duration" type="radio" value="1-Year"/>
  <span>1-Year</span>
</label>

<label>
  <input name="contract_duration" type="radio" value="2-Years"/>
  <span>2-Years</span>
</label>

The problem with your code is that querySelector only returns the first matched element. If you want the event listener on all of them, you should use querySelectorAll and loop through the elements.

Like this:

if(document.querySelector('input[name="contract_duration"]')){
    document.querySelectorAll('input[name="contract_duration"]').forEach((elem) => {
        elem.addEventListener("click", function(event){
            var item = event.target.value;
            console.log(item);
        });
    });
}
Related