3

This is a problem I was having:

I am trying to access the button inside of the div and make each of them log its own text content on click. But all of them display all of the text content. And it has to be in vanilla JavaScript.

const array = document.querySelectorAll(".div"); array.forEach(button => { button.addEventListener('click', function (){ console.log(this.textContent) }) });
 <div class=div> <button>Button 1</button> <button>Button 2</button> <button>Button 3</button> <button>Button 4</button> </div>

I Used a for loop and a for each loop. None worked.

3
  • 1
    you can use array = document.querySelectorAll(".div > button") Commented Aug 6, 2024 at 15:32
  • 2
    @Mehdi querySelectorAll() returns an iterable (a NodeList), not an array. Many of array's methods don't exist on it, but it can easily be converted to an array with Array.from(). Commented Aug 6, 2024 at 17:34
  • 1
    @Oskar Grosser thanks for your correct point, absolutely it is a NodeList just rewrite it and focused more on ('.div > button) for OP to select his btns. We can also as you said make an array by using Array.from(document.querySelectorAll..). Again good that you pointed it out. He probably should correct the question title as well Commented Aug 6, 2024 at 17:41

3 Answers 3

4

You can access the event.target to get the context of the click.

document.querySelectorAll('.my-div').forEach(function(button) { button.addEventListener('click', function(event) { console.log(event.target.textContent) }) });
<div class="my-div"> <button>Button 1</button> <button>Button 2</button> <button>Button 3</button> <button>Button 4</button> </div>

Even better, you could delegate the event and reuse the listener for any button that matches the selector.

document.querySelector('.my-div').addEventListener('click', function(event) { if (event.target.matches('button')) { handleClick(event); } }); function handleClick(event) { console.log(event.target.textContent); }
<div class="my-div"> <button>Button 1</button> <button>Button 2</button> <button>Button 3</button> <button>Button 4</button> </div>

Sign up to request clarification or add additional context in comments.

1 Comment

Cool tip! Somehow I always end up calling variables but they are not always needed... Thanks! :)
2

Your code is looping through the array of div elements and adding an event handler to the div element, rather than the buttons.

but instead of looping through all the buttons, use "event delegation" where you set up a single handler at an ancestor of all the buttons (the div in this case) and check the event.target, which refers to the object that actually fired the event. Much simpler approach - one event handler, no loops, no arrays.

// Set up event handler at the object that contains all the buttons document.querySelector(".div").addEventListener("click", function(evt){ // Check to see if the event originated at an element you care to handle if(evt.target.nodeName === "BUTTON"){ console.log(event.target.textContent); } });
<div class=div> <button>Button 1</button> <button>Button 2</button> <button>Button 3</button> <button>Button 4</button> </div>

Comments

1

I was calling all the elements with the class .div.

What I wanted was to call the buttons inside the element with the class .div.

Solution: add 'button' after .div:

const array = document.querySelectorAll(".div button"); 

And now it works:

const array = document.querySelectorAll(".div button"); array.forEach(button => { button.addEventListener('click', function (){ console.log(this.textContent) }) });
<div class=div> <button>Button 1</button> <button>Button 2</button> <button>Button 3</button> <button>Button 4</button> </div>

1 Comment

See my answer for much simpler approach.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.