0

So I'm currently busy with learning JavaScript. I created some dynamic buttons and I tried to add an addEvenListener to it. But it doesn't work and I can't figure it out why it doesn't work. I'm just testing some stuff and I try to create buttons with values from the localstorage. It is almost working, only the addEvenListener isn't working. I just want a simple alert with the key from the localstorage.

for (var i = 0; i <= localStorage.length-1; i++) {
    var categoryButton = document.createElement('input');
    categoryButton.setAttribute('class', 'forumMenu');
    categoryButton.setAttribute('type', 'button');
    categoryButton.setAttribute('name', localStorage.key(i));
    categoryButton.setAttribute('value', localStorage.key(i));
    categoryButton.setAttribute('id', localStorage.key(i));
    categoryButton.addEventListener('click', function(col){
    alert(col);
}(localStorage.key(i)),true);
    forumMenu.appendChild(categoryButton);
}

Does anyone know why it doesn't work?

Jari
  • 28
  • 5

3 Answers3

1

You're not passing a function to EventTarget.addEventListener(). You're immediately executing and passing the result of this:

function (col) {
  console.log(col);
}(localStorage.key(i))

... which is undefined. You can ammend that by using the following syntax:

categoryButton.addEventListener('click', (function(col) { 
   // return a function to addEventListener
   return function(){
      console.log(col);
   }
})(localStorage.key(i)),true);

Here's a demo:

var input;
for (var i = 0; i <= 5; i++) {
  input = document.createElement('input');
  input.type = "button"
  input.value = i;
  input.addEventListener('click', function(i) {
    // return a function to addEventListener
    return function() {
      console.log(i);
    }
  }(i), true);
  document.body.appendChild(input);
}
canon
  • 40,609
  • 10
  • 73
  • 97
  • This works great, but I have a special div in my html for the buttons. how can I add those buttons to that div? – Jari Feb 25 '15 at 15:24
  • Replace `document.body` with the appropriate element. That demo doesn't deal with `localStorage` either. It's merely intended as a simple sample for adding a handler in a loop. – canon Feb 25 '15 at 15:24
  • I noticed it, but wen I try to change the document.body, the eventlistener won't work again. I changed document.body to document.getElementById("forumMenu"); – Jari Feb 25 '15 at 15:29
  • 1
    @Jari your code suggest that you already have a direct reference to `forumMenu`. I couldn't say why it's not working. I've provided a minimal, functioning code sample. You must adapt it to your needs or provide more information. – canon Feb 25 '15 at 15:30
0

You stored the value in the id attribute, so just use it:

 for (var i = 0; i <= localStorage.length-1; i++) {
    var categoryButton = document.createElement('input');
    categoryButton.setAttribute('class', 'forumMenu');
    categoryButton.setAttribute('type', 'button');
    categoryButton.setAttribute('name', localStorage.key(i));
    categoryButton.setAttribute('value', localStorage.key(i));
    categoryButton.setAttribute('id', localStorage.key(i));

    categoryButton.addEventListener('click', function () {alert(this.getAttribute('id'));});
 document.body.appendChild(categoryButton);
 }

In the event handler, this references the <input> element itself, so you can just retrieve the attribute value.

Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
Ôrel
  • 7,044
  • 3
  • 27
  • 46
  • 2
    Please **explain** the changes you made and why/how it solves the problem. – Felix Kling Feb 25 '15 at 15:18
  • You certainly don't "have to" store data in the id. And I'd argue that storing arbitrary data in the id is a bad pattern. – Felix Kling Feb 25 '15 at 15:56
  • I don't say you "have to", just use what it is already stored. I don't the goal, perhaps store the id is better than the value. – Ôrel Feb 25 '15 at 15:58
  • Oh sorry, I guess my mind inserted a "to" there. Btw, `this.id` would be a simpler way to get the value. – Felix Kling Feb 25 '15 at 16:13
  • @FelixKling as well as a bunch of `setAttribute()` calls for values exposed as properties... but that comes from the OP's code. – canon Feb 26 '15 at 15:25
-2

Thats because you are assigning that eventlistener to an object that is not still in the DOM (thats because you created this element after the DOM was loaded)

Try this:

categoryButton.onclick = function(col){
    alert(col);
}

You can either declare a function to a var and then reasign this function to the event handler:

var myFunction = function(){
    alert("I'm a function");
}

myElement.onclick = myFunction;
  • 1
    So you believe that `addEventListener` only works if the element is in the document? Why? And why shouldn't that apply to `onclick` as well? – Felix Kling Feb 25 '15 at 15:17
  • Well, if you want to "click" the element, it must be in the document, isn't it? I figured out he was trying to add this element after the page is loaded. – David Martin Feb 25 '15 at 15:24
  • 1
    Sure, one cannot click the element before its in the document, but you can bind an event handler as soon as you have a reference to it. However I'm still curious why you think that onclick would work (and addEventListener wouldn't). – Felix Kling Feb 25 '15 at 15:49