2

When I create a couple of buttons using forEach then add an event listener to each and then try to access the element itself inside that listener, it just defaults to the last one.

HTML:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <template id="button-template">
        <button></button>
    </template>

    <script src="./bug.js"></script>
</body>
</html>

Js:

const button_template = document.getElementById("button-template")

for(let i = 0; i < 10; i++) {
    clone = button_template.content.cloneNode(true)
    btn = clone.querySelector("button")

    btn.addEventListener("click", () => {
        btn.style.display = "None"
    })

    btn.innerHTML = i.toString()

    document.querySelector("body").appendChild(clone)
    console.log("something")
}

In this example, I try to make each button remove itself. But all of them just remove the tenth one. How can I fix this? I already tried using this or selfbut I get the same result

1 Answer 1

1

Here's one alternative, out of many: events have an event.target property, which points to the object to which the event was originally dispatched.

Thus, this is your code with that change:

const button_template = document.getElementById("button-template")

for (let i = 0; i < 10; i++) {
  clone = button_template.content.cloneNode(true)
  btn = clone.querySelector("button")

  btn.addEventListener("click", event => {
    event.target.style.display = "None"
  })

  btn.innerHTML = i.toString()

  document.querySelector("body").appendChild(clone)
  console.log("something")
}
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <template id="button-template">
        <button></button>
    </template>

  <script src="./bug.js"></script>
</body>

</html>

However, I believe the most important thing here is understanding why btn is always the last button: because you miss a const or let or var, your btn is a global variable, being constantly updated at each loop.

Thus, a simple const will fix this:

const button_template = document.getElementById("button-template")

for (let i = 0; i < 10; i++) {
  clone = button_template.content.cloneNode(true)
  const btn = clone.querySelector("button")

  btn.addEventListener("click", () => {
    btn.style.display = "None"
  })

  btn.innerHTML = i.toString()

  document.querySelector("body").appendChild(clone)
  console.log("something")
}
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <template id="button-template">
        <button></button>
    </template>

  <script src="./bug.js"></script>
</body>

</html>

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

Comments

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.