2

I am trying to add event listers for all checkboxes inside a class. I am able to add event listener to class. How can I add to all checkboxes inside that class?

var classname = document.getElementsByClassName("classname");

var myFunction = function() {
    var attribute = this.getAttribute("data-myattribute");
    alert(attribute);
};

for (var i = 0; i < classname.length; i++) {
    classname[i].addEventListener('click', myFunction, false);
}
Kurkula
  • 6,386
  • 27
  • 127
  • 202

4 Answers4

5

Since JS events bubble up to parent elements you only have to attach ONE event listener to the parent element and it will catch every event triggered by its children.

document.querySelector('#container').onclick = function(ev) {
  if(ev.target.value) {
    console.log(ev.target.checked, ev.target.value);
  }
}
<div id="container">
  <input type="checkbox" value="Bike">I have a bike<br>
  <input type="checkbox" value="Car">I have a car<br>
  <input type="checkbox" value="Flower">I have a flower<br>
</div>
Olian04
  • 6,480
  • 2
  • 27
  • 54
  • are you sure? sounds very interesting? – Kurkula Nov 27 '17 at 19:14
  • @Kurkula yes I'm sure, and yes it is :) I provided a link to another SO question talking about it, if you want to read some more. – Olian04 Nov 27 '17 at 19:15
  • 2
    @Kurkula, this is the preferred approach as 1) bubbling is how the DOM works 2) it saves you having all those event listeners, 3) If you decided to add a checkbox dynamically to the page, the function would still work even if you didn't specifically attach a listener to it. – Andy Nov 27 '17 at 19:53
4

You could use querySelectorAll

const checkboxes = document.querySelectorAll( '.example input[type=checkbox]' );

var myFunction = function() {
    var attribute = this.getAttribute("data-myattribute");
    console.log( attribute );
};

for (var i = 0; i < checkboxes.length; i++) {
    checkboxes[i].addEventListener('click', myFunction, false);
}
<div class="example">
  <input type="checkbox" data-myattribute="1" />
  <input type="checkbox" data-myattribute="2" />
</div>

Or you could just use the event.target property of your old event listener like this:

var classname = document.getElementsByClassName("example");

var myFunction = function(event) {
  var attribute = event.target.getAttribute("data-myattribute");
  console.log(attribute);
};

for (var i = 0; i < classname.length; i++) {
  classname[i].addEventListener('click', myFunction, false);
}
<div class="example">
  <input type="checkbox" data-myattribute="1" />
  <input type="checkbox" data-myattribute="2" />
</div>

Of course, with the second approach you need to check, if you really deal with a checkbox.


In your case though I would rather use change events instead of click. That way, you can use it within a label and have the label clickable, instead of only the checkbox itself.

const checkboxes = document.querySelectorAll( '.example input[type=checkbox]' );

var myFunction = function( event ) {
    var attribute = event.target.getAttribute("data-myattribute");
    console.log( attribute );
};

for (var i = 0; i < checkboxes.length; i++) {
    checkboxes[i].addEventListener('change', myFunction, false);
}
<div class="example">
  <label>
    <input type="checkbox" data-myattribute="1" /> test1
  </label>
  <label>
    <input type="checkbox" data-myattribute="2" /> test2
  </label>
</div>
lumio
  • 7,428
  • 4
  • 40
  • 56
2

You don't really need to. Just check the event.target to see if a checkbox was clicked.

var myFunction = function(event) {
    if (event.target.type === "checkbox") {
      var attribute = this.getAttribute("data-myattribute");
      alert(attribute);  
    }
};

Also, there's shorter syntax available for getting data attribute values.

var attribute = this.dataset.myattribute;

You also probably want a change event rather than a click event.

1

You can use document.querySelectorAll This document.querySelectorAll(".classname input[type='checkbox']"); will select the parent element by it's class and then the child inputs

var classname = document.querySelectorAll(".classname input[type='checkbox']");
classname.forEach(function(item) {
  item.addEventListener('click', function() {
    var attribute = this.getAttribute("data-myattribute");
    console.log(attribute);

  })
})
<div class="classname">
  <input type="checkbox" data-myattribute="1">
  <input type="checkbox" data-myattribute="2">
  <input type="checkbox" data-myattribute="3">
  <input type="checkbox" data-myattribute="4">

</div>
brk
  • 48,835
  • 10
  • 56
  • 78