1

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

6
  • 1
    You are adding the event handlers in a loop, aren't you? Commented Aug 7, 2012 at 12:59
  • Yes, sure, so the value of Data is changing every loop and the value of the function is not the correct for the 'li' element I'm doing a click on. Commented Aug 7, 2012 at 13:00
  • @Nuxy so please show your complete loop... Commented Aug 7, 2012 at 13:01
  • I've added some more code, but I think it doesn't give really extra info. Commented Aug 7, 2012 at 13:04
  • @Nuxy now just add your .onclick function body and we have a free reputation fest Commented Aug 7, 2012 at 13:05

3 Answers 3

6

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/

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

Comments

3

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);

4 Comments

Using 'onclick' is just wrong. The reason it's not working for the OP is explained in the documentation linked by Alexander (the same problem occurs with addEventListener - but it doesn't break other things too).
@symcbean I don't know what you are talking about but addEventListener is completely irrelevant and any answer merely stating that one should use it is just a comment and not an answer.
I will try the solution tomorrow at the office. Will say something about if it works.
With the first solution every time a 'li' is added it runs the function, without even do the 'click'. Don't know exactly why, but I learnt more about events and functions. I'm taking the solution of 'Diode' it requires an external array but worked. Thanks for the time spent.
3

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.

3 Comments

I will try the solution tomorrow at the office. Will say something about if it works.
Thanks for the effort, but the solution of 'Diode' totally worked, it's like what you added.
it works very well. but ... how did you find this solution !! :D

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.