Christian Lundahl
Christian Lundahl

Reputation: 2050

Adding event listeners to multiple elements

I've been struggling with this for a good couple of hours now.

I want to add an event listener to all <select>s on a page and I've got this piece of code so far:

onload = function(e) {
    sels = document.getElementsByTagName('select');
    for(i=0; i<sels.length; i++) {
        sels[i].addEventListener('change', alert('test!'), false);
    }
}

This only triggers the alert when the page is loaded and not when I change the value in any of my <select>s.

Can I get a nudge in the right direction, please? :-)

Upvotes: 11

Views: 40610

Answers (6)

mplungjan
mplungjan

Reputation: 178403

I always recommend delegation - if the inputs are in the same container, then you can do this

window.addEventListener("load", function() { // on page load
  document  // or a closer static container
    .addEventListener("input", function(e) { // input or change
    const tgt = e.target;
    if (tgt.tagName === "SELECT") {
      const id = tgt.id;
      console.log("You changed", id)
    }
  });
});
<div id="inputContainer">
  <h1>Change the select</h1>
  <select id="sel1">
    <option value="">Please select</option>
    <option value="1">One</option>
    <option value="2">Two</option>
  </select>
  <select id="sel2">
    <option value="">Please select</option>
    <option value="1">One</option>
    <option value="2">Two</option>
  </select>
</div>

Upvotes: 0

isapir
isapir

Reputation: 23600

I created the following simple function, which iterates over all of the elements that match the selector, and add an event listener for the event with the passed handler.

This is similar functionality for jQuery's $(selector).on(event, handler)

function addEventListeners(selector, event, handler, useCapture){

    useCapture = useCapture || false;

    Array.prototype.forEach.call(
        document.querySelectorAll(selector)
       ,function(el, ix) { 
          el.addEventListener(event, handler, useCapture);
        }
    );
}

So for the OP the way to use this function would be like so:

addEventListeners("select", "change", function(evt){ console.log(evt); });

See also my answer for Event listener for current and future elements

Upvotes: 1

Ayush Sharma
Ayush Sharma

Reputation: 2107

Event Bubbling is the important concept in javascript, so if you can add event on DOM directly, you can save some lines of code :

document.addEventListener('change', function(e){
  if(e.target.tagName=="SELECT"){
   alert('SELECT CHANGED');
  }
})

Upvotes: 0

antyrat
antyrat

Reputation: 27765

You need to have there anonymous function for that as you invoke alert() function immediately in your example:

 ... .addEventListener('change', function() { alert('test!')}, false ...

For now according to your code addEventListener tries to add result of undefined (return of alert() function).

Or you can just pass function handler for that:

function alertMe() {
    alert( 'test!' );
}
...

... .addEventListener('change', alertMe, false ...

Note: that by making somefunction(arg[, arg...]) call you reference not to function, but to what function returns.

Upvotes: 9

Cerbrus
Cerbrus

Reputation: 72967

Aside from wrapping the alert in a function, like mentioned before, don't use getElementsByTagName for every iteration of the loop:

onload = function(e) {
    sels = document.getElementsByTagName('select');
    for(i=0; i<sels.length; i++) {
        sels[i].addEventListener('change', function(){alert('test!')}, false);
    }
}

You have the list of select elements saved to a variable, it's not necessary, not to mention inefficient to get all these elements, each loop iteration.

Upvotes: 6

Will C.
Will C.

Reputation: 599

You are executing the alert() function immediately, you need to pass the addEventListener function a function instead, so:

onload = function(e) {
    sels = document.getElementsByTagName('select');
    for(i=0; i<sels.length; i++) {
        document.getElementsByTagName('select')[i].addEventListener('change', function () { alert('test!'); }, false);
    }
}

Upvotes: 0

Related Questions