Nuxy
Nuxy

Reputation: 384

How to add onclick event while creating an element with JavaScript?

I have a script where I'm appending elements to a list. I would need that when I click the element a function is called, and for this function the value of a variable when creating the li is needed (it's the li content).

I've checked solutions like adding newLi.onclick = function(){...}.

The problem with this solution is that I'm not getting the right value in the function, I get the value of another element in the list.

Right now this is how I'm creating the elements:

var ULlist = document.getElementById('ULid');
for(i=0;i<data.length;i++){
   var Value = data[i] //function to get data
   var newLi = document.createElement('li');
   newLi.appendChild(elements.createTextNode(Value));
   newLi.onclick = function(){alert(Value)} //not displaying the right value
   ULlist.appendChild(newLi);
}

So the question is, is there any way to create te onclick event giving to the element the right value of the variable?

Edit: I've added a portion more of code. Li's are being created, and information displayed correctly, the only problem is when trying to create the event that it's not giving the right value, that should be the value cointained at the li

Upvotes: 1

Views: 12611

Answers (3)

sedran
sedran

Reputation: 3566

When I experienced this problem, I solved it like this:

var ULlist = document.getElementById('ULid');
for(var i=0; i<data.length; i++){
   var index = i;
   (function() {
   var Value = data[index] //function to get data
   var newLi = document.createElement('li');
   newLi.appendChild(elements.createTextNode(Value));
   newLi.onclick = function() { ... };
   ULlist.appendChild(newLi);
   }());
}

Edit: Today, I remember another thing about for scope. It is another solution to send parameter 'i' to function inside the loop:

var ULlist = document.getElementById('ULid');
for(var i=0; i<data.length; i++){
   (function(index) {
       var Value = data[index] //function to get data
       var newLi = document.createElement('li');
       newLi.appendChild(elements.createTextNode(Value));
       newLi.onclick = function() { ... };
       ULlist.appendChild(newLi);
   }(i));
}

Try this and let me know if it works.

Upvotes: 3

Diode
Diode

Reputation: 25135

You can achieve this by creating function inside and keeping the value in the scope of that function.

var data = [10, 20, 30, 40, 50, 60, 70];
addItems = function() {
    var list = document.getElementById("list");
    for (var i = 0; i < data.length; i++) {
        var newLi = document.createElement("li");
        newLi.innerHTML = i + 1;
        list.appendChild(newLi);
        (function(value){
        newLi.addEventListener("click", function() {
           alert(value);
        }, false);})(data[i]);
    }

}​

jsfiddle : http://jsfiddle.net/Qf5JZ/1/

Upvotes: 6

Alexander Pavlov
Alexander Pavlov

Reputation: 32286

Use DOM2 event listeners, in particular the element.addEventListener API:

function clickHandlerFor(data) {
    return function(event) {
        var li = event.target;
        // do something with data and li.
    };
}

for (...) {
    var Data = ... //function to get data
    var newLi = elements.createElement('li');
    newLi.appendChild(elements.createTextNode(Data));
    newLi.addEventListener("click", clickHandlerFor(Data), false);
    ULlist.appendChild(newLi);
}

Another option is much simpler: use the TextNode value in your handler:

function handler(event) {
    var dataValue = event.target.firstChild.nodeValue; // value of TextNode created by elements.createTextNode(Data)
    // handle dataValue
}

newLi.addEventListener("click", handler, false);

Upvotes: 3

Related Questions