0

I'm searching how to find the index of the element clicked in my foreach loop. Since this type of foreach loop isn't used much, I couldn't find any existing topics on this specific question.

This is my code now (css for clarity):

var toggleExtras = document.querySelectorAll(".toggle-extra");

Array.prototype.forEach.call(toggleExtras, function (toggleExtra) {
    toggleExtra.addEventListener('click', function () {
   console.log(index);
  })
});
.toggle-extra {
 background-color: #C9C9C9;
 padding: 10px;
 margin: 20px 0px;
 color: #000;
 width: 200px
 }
<div class="toggle-extra">Title</div>
<div class="toggle-extra">Text</div>
<div class="toggle-extra">Button</div>
<div class="toggle-extra">Link</div>

I found the following code in another topic, which seems to work;

document.querySelectorAll("button").forEach((button, index) => {
 button.onclick = (event) => {
  console.log("You clicked button number " + index);
 }
})

How do I use 'index' like this code in my specific foreach loop? I've tried the following without succes;

Array.prototype.forEach.call(toggleExtras, index, function (toggleExtra) {
Array.prototype.forEach.call(toggleExtras, function (toggleExtra), index {

Please don't advies me to use a different foreach method, I need to use exactly this one. Does anyone know how to do this?

1
  • 2
    You can obtain it through the second parameter function (toggleExtra, index) { Commented Feb 15, 2021 at 11:01

3 Answers 3

1

index is passed to forEach callback, catch it here


Array.prototype.forEach.call(toggleExtras, function (toggleExtra, index) {
Sign up to request clarification or add additional context in comments.

Comments

1

Add the index to the calling function, like so.

var toggleExtras = document.querySelectorAll(".toggle-extra");

Array.prototype.forEach.call(toggleExtras, function (toggleExtra, index) {
    toggleExtra.addEventListener('click', function () {
   console.log(index);
  })
});
.toggle-extra {
 background-color: #C9C9C9;
 padding: 10px;
 margin: 20px 0px;
 color: #000;
 width: 200px
 }
<div class="toggle-extra">Title</div>
<div class="toggle-extra">Text</div>
<div class="toggle-extra">Button</div>
<div class="toggle-extra">Link</div>

Comments

0

I would suggest you to simplify your logic. Avoid attanching events inside loops, its a bad practice. Instead, attach the event in the parent element of the target elements. If there is other undesired elements inside the parent element, just filter them with an if checking the class inside the event function.

document.querySelector('div.parent').addEventListener('click', (e) => {
  console.log('index', e.target.dataset.index);
});
div.toggle-extra {
  cursor: pointer
}
<div class="parent">
  <div class="toggle-extra" data-index="0">Title</div>
  <div class="toggle-extra" data-index="1">Text</div>
  <div class="toggle-extra" data-index="2">Button</div>
  <div class="toggle-extra" data-index="3">Link</div>
</div>

The index is defined in a data attribute, which can be anything, not only index, like a name(data-name="title") for instance.

5 Comments

Adding an event-listener to a parent so that descendants also activate that listener is called Event Delegation and has to do with Event Bubbling. Just in case someone is interested...
e.target is "problematic"; it may contain the wrong element. Especially with more markup inside you'd want to get the actual node you're looking for: const button = e.target.closest(".toggle-extra"); You can use this to filter out unwanted clicks if(!button) return; (you clicked on something that's not a .toggle-extra inside of .parent) and you can also use it to get the index: const index = button.dataset.index or const index = Array.prototype.indexOf.call(e.currentTarget.querySelectorAll(".toggle-extra"), button);.
Well, the thing is. I simplified my markup here. The div's with class '.toggle-extra' actually are div's with a lot of child, grandchild and great granchild etc. elements. That's why this won't actually be a good method for me. Thanks though!
@Sybrentjuh nested markup ain't a problem to this approach per se. It needs to be handled, but that's why I made the detailed comment above. And since you already handle your click-handler in a loop, I don't think they contain anything that could not be handled by this approach either. Just saying. IMO, this here is not exactly an answer to your question, but it's the better approach to your problem and its context.
@Thomas Nice point! closest() should be used in this case for sure.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.