-1

I got a lil problem. I want to create JavaScript buttons with a onclick on them but it's not working. Here is a lil code that matches my problem:

for (var i = 0; i < 3; i++) {
  $('menu').innerHTML += '<button id="btn' + i + '">Button' + i + '</button>';
  $('btn' + i).onclick = function (i) {
    alert(i);
  };
}

The real situation is a lil bit more complicated. Its a small webapplication for a device like google glass. The navigation is via voice but for support purpose we have to display buttons on the site if we enter it with a normal browser.

Anyone knows what that isn't working, I thought JavaScript would be working with call-by-value? Maybe there is even a better solution?

Edit:

$ ist just a return of document.getElementById and that should work without #. The buttons are created, the last button is working. Thats why I said I thought it works with call-by-reference cause to me it seems like once I change the name of i it is changing the onclick, which is the only reason I can think of why only the last one works.

Edit2:

It looks like the problem was the innerHTML += which removed the eventListeners. So I fixed that problem but I still can't pass parameters. My trys look like this:

for (var i = 0; i < 3; i++) {
  var btn = document.createElement('button');
  btn.setAttribute('id', 'btn' + i);
  var btnText = document.createTextNode('Button' + i);
  $('menu').appendChild(btn);
  $('btn' + i).appendChild(btnText);
  $('btn' + i).onclick = function () {
    alert(i);
  }
}

Ok problem seems to be that the function gets called later when i is 3. But that problem wasn't part of my real problem. appendChild was the solution. The real application is working now as it should.

Thanks ladies :)

gobnepla
  • 644
  • 1
  • 5
  • 16

2 Answers2

1

That for loop will have ended by the time your selector code is being executed, you'll need a closure.

for (var i = 0; i < 3; i++) {
   $('menu').innerHTML += '<button id="btn' + i + '">Button' + i + '</button>';

   (function(i) {
       document.getElementById("btn" + i).onclick = function (i) {
           alert(i);
       };
   })(i);
}
tymeJV
  • 103,943
  • 14
  • 161
  • 157
  • Ok understand its a scope problem. Though that code gives me pretty much the same problem. Only the last button is doing something. – gobnepla Dec 16 '13 at 16:06
  • 2
    @user1900980: Whenever you use `.innerHTML +=`, you are destroying and recreating the existing DOM elements. Event handlers you have bound previously will be lost. Instead of using `innerHTML` you should use other DOM manipulation methods, such as `appendChild`. – Felix Kling Dec 16 '13 at 16:10
  • appendChild has helped me so all buttons are working but I get the same value for all three buttons. – gobnepla Dec 17 '13 at 10:45
1

Asuming $ is jQuery:

var menu = $('menu')
for (var i = 0; i < 3; i++) {
  $('<button id="btn' + i + '">Button' + i + '</button>').on('click', (function (j) {
    // Created a closure here, that has access to the original i as j.
    alert(j);
  })(i)).appendTo(menu);
}
Poetro
  • 574
  • 3
  • 9