1

I am trying to assign a click event handler to dynamically created buttons that once clicked, will return the ID of the clicked button in vanilla Javascript without any frameworks. Yet I can't seem to get the events to handle properly, here's the code

let h = document.getElementsByClassName("buttons");

h.forEach(function() {
 addEventListener("click", function() {
  alert(this.id);
 });
};
lecidious
  • 52
  • 7
  • Possible duplicate of [Event binding on dynamically created elements?](https://stackoverflow.com/questions/203198/event-binding-on-dynamically-created-elements) – Heretic Monkey Mar 04 '19 at 16:29
  • @HereticMonkey That may be the next problem, but right now the script won't do anything else but throwing a `ReferenceError` (unless there's a custom `addEventListener()` function...) – Andreas Mar 04 '19 at 16:32
  • @Andreas Presumably after reading the answers to that question it would become clear that they don't even need to iterate over them :). – Heretic Monkey Mar 04 '19 at 16:34

3 Answers3

1

The method document.getElementsByClassName() returns and HTMLCollection wich is an array-like object (but not an array), so you can't use forEach() on it to iterate over his elemtents. Instead, you can use a for loop:

let h = document.getElementsByClassName("buttons");

for (let i = 0; i < h.length; i++)
{
    h[i].addEventListener("click", function()
    {
        alert(this.id);
    });
}
<button id="id1" class="buttons">BUTTON 1</button>
<button id="id2" class="buttons">BUTTON 2</button>

Alternatively, you can spread his element on an array, and then use forEach() on it:

let h = document.getElementsByClassName("buttons");

[...h].forEach(function(btn)
{
    btn.addEventListener("click", function()
    {
        alert(this.id);
    });
});
<button id="id1" class="buttons">BUTTON 1</button>
<button id="id2" class="buttons">BUTTON 2</button>
Shidersz
  • 15,614
  • 2
  • 15
  • 40
  • @Andreas I have tried it directly on latest `firefox` version and it didn't work, the method `getElementsByClassName` returns a `HTMLCollection`, not a `NodeList` – Shidersz Mar 04 '19 at 17:04
  • You're right... I confused it with [`document.querySelectorAll()`](https://developer.mozilla.org/en-US/docs/Web/API/Element/querySelectorAll) which returns a `NodeList` – Andreas Mar 04 '19 at 17:07
1

Try

let h = document.getElementsByClassName("buttons");

[...h].forEach(b => {
  b.addEventListener("click", () => {
    alert(b.id);
  });
});
<button id="btn-id-1" class="buttons">Btn 1</button>
<button id="btn-id-2" class="buttons">Btn 2</button>
<button id="btn-id-3" class="buttons">Btn 3</button>
Kamil Kiełczewski
  • 53,729
  • 20
  • 259
  • 241
  • This worked perfectly, thank you! One more thing though, as I'm still kinda inexperienced with js, can you explain what the [...h] is/does? – lecidious Mar 04 '19 at 16:44
  • 1
    `[...h]` cast HTMLCollection into JS array which has forEach method. The three dots `...` is [spread syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax) – Kamil Kiełczewski Mar 04 '19 at 16:47
0
let h = document.getElementsByClassName("buttons");

h.forEach(function(element) {
    element.addEventListener("click", function() {
        alert("Hello");
    });
};