Add event listeners to multiple DOM elements in Javascript
Published: 2022-08-19 05:26:00

#### Adding an event listener to a DOM element in its simplest form involves doing two things:

1. _Selecting the element from the DOM_
   
     Ex. `const elem = document.querySelector('#name-of-id')`
(here we are selecting the element by its id using the CSS Selector '#' instead of the `getElementById()` method)

2. _Adding an event listener to the selected element_
 
     Ex. `elem.addEventListener("click", renderAction)`
(where `renderAction` is the callback function that is called after the event is clicked.)

&nbsp;

> ###**But what if we wanted to select multiple elements of the DOM where we wanted to add click event listeners to all of the elements without writing addEventListener() for each?**

&nbsp;

We could achieve this by doing three things,

**1. Selecting all the elements using the method `querySelectorAll()`**
**2. Traversing the NodeList Collection of elements using a loop like `forEach`**
**3. Adding an event listener to each of the elements on the NodeList**

&nbsp;

## Using querySelectorAll() and the NodeList

Say we have the following html:

```javascript
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title> Instruments </title>
  </head>

  <body>
    <div id="instrument-container">
      <div class="instrument">Piano</div>
      <div class="instrument">Trumpet</div>
      <div class="instrument">Saxophone</div>
      <div class="instrument">Flute</div>
    </div>

    <script src="./index.js"></script>
  </body>
</html>
```

>We can use javascript to select all of the elements with a class of `"instrument"`

```javascript
const instElems = document.querySelectorAll('.instrument')
```

In this case, we are using the CSS selector `'.'` dot to specify to only select all elements with `"instrument"` as their class.

The `querySelectorAll()` method will then add these elements to a NodeList collection. Remember that the DOM is a tree of Nodes so when we select from the DOM we are selecting its Nodes.

&nbsp;

## Traversing the NodeList with forEach()

Just like arrays use the forEach() loop to traverse its elements, NodeList Object also has a built-in forEach() method for traversal.

In the following javascript we traverse the NodeList `instElems`:

```javascript
const instElems = document.querySelectorAll(".instrument")

instElems.forEach(elem => {
    console.log(elem)
})
```
**Let's break that code down:**

- `instElems` is the NodeList Collection
- `forEach` traverses each element which is passed as a variable `elem` to an anonymous function (using arrow notation)
- for every element `elem` of `instElems`, we call the anonymous function and `console.log` the element

**This is the output:**


![Output](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dafll2h3q7s66rmn1man.png)

> As you can see, it console logs all of the `<div>` elements with `"instrument"` as their class

&nbsp;


## Adding a Click Event Listener to All Elements in NodeList

Now that we have our NodeList, we will traverse it again but this time we will add an event listener for every node.

The following code does this:


```javascript
const instElems = document.querySelectorAll(".instrument")

instElems.forEach(elem => {
    elem.addEventListener("click", (event) => {
        console.log(event.target.innerText, "clicked")
    })
})
```
- So for each element of `instElems` (every instrument `<div>`) we will add an event listener.

- The event listener will call the anonymous function for that `<div>` when the `<div>` is clicked.

- The anonymous function then console logs the text inside that `<div>` element and a string saying it was clicked.

**Demo:**


![Demo](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5312djqyo4l54pxv6ekw.gif)

&nbsp;

## Conclusion

We explored how to add event listeners such as a `"click"` to multiple DOM elements in a few lines of code. We did it by using a built-in selector method which then adds the DOM elements to a NodeList collection without having to traverse them ourselves. The only traversing would happen at the point of applying the event listeners to the elements. We did this by using a built-in loop method of NodeList. 

Another great thing about having the `<div>`'s stored in a NodeList Collection is that now you can reference that same collection of `<div>`'s when you need it without having to select them every time. 

Tip: If you ever need to do more with the collection, you can also transform the collection into an array by using the [Array.from()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from) method.

## References:
>[MDN Doc - NodeList](https://developer.mozilla.org/en-US/docs/Web/API/NodeList)
>[W3 Schools - CSS Selectors](https://www.w3schools.com/cssref/css_selectors.asp)
>[MDN Doc - addEventListener](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener)
>[MDN Doc - querySelectorAll](https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelectorAll)
>[Instruments Image](https://c7.alamy.com/comp/EGCPDR/1980s-musical-instruments-piano-saxophone-flute-trumpet-EGCPDR.jpg)