timzand
timzand

Reputation: 3

How do I add an unique argument when adding onclick events during a loop?

What I'm trying to do is add a unique onclick on each button using parameters so I can identify each of the buttons when they are clicked, using function parameters.

function createProducts() {
    for(var i = 0; i < products.length;i++) {
        var li = document.createElement("li");
        li.className = "products";
        li.onclick = "purchase(" + i + ")";
        li.innerHTML = products[i][0] + "<span class=\"price\"> Klikk/s: " + products[i][1] + " Pris: " + products[i][2] + "</span>";
        document.getElementById("list").appendChild(li);
    }
}

function purchase(id) {
    alert(id);
}

I've tried

li.onclick = purchase(i);

And

li.onclick = "purchase(" + i + ")";

But none of these work.

Upvotes: 0

Views: 69

Answers (2)

DontVoteMeDown
DontVoteMeDown

Reputation: 21465

Try this in the li creation loop:

li.onclick = purchase;
li.dataset.index = i;

In the purchase event:

function purchase(id) {
    var index = this.dataset.index;
}

More about data attributes(dataset) here and here.

Upvotes: 0

T.J. Crowder
T.J. Crowder

Reputation: 1074375

You have a couple of choices. You can create a variable for your handler to close over that doesn't change (like i does). You can do that in your case with Function#bind:

function createProducts() {
    for(var i = 0; i < products.length;i++) {
        var li = document.createElement("li");
        li.className = "products";
        li.onclick = purchase.bind(li, i); // <====
        li.innerHTML = products[i][0] + "<span class=\"price\"> Klikk/s: " + products[i][1] + " Pris: " + products[i][2] + "</span>";
        document.getElementById("list").appendChild(li);
    }
}

Function#bind returns a function that, when called, will call the original with a specific this value (we're setting it to the element reference) and any arguments you passed bind (in our case, i). Since the value that gets bound is the value of i when we call bind, not when the click occurs, it doesn't change like i would.

Alternately, you can store the id on the element itself as an attribute, and then use that in your handler:

function createProducts() {
    for(var i = 0; i < products.length;i++) {
        var li = document.createElement("li");
        li.className = "products";
        li.setAttribute("data-id", i);
        li.onclick = purchase;
        li.innerHTML = products[i][0] + "<span class=\"price\"> Klikk/s: " + products[i][1] + " Pris: " + products[i][2] + "</span>";
        document.getElementById("list").appendChild(li);
    }
}

function purchase() {
    // Use this.getAttribute("data-id") here to get the value
}

Note that in both cases, we're using real function references, not strings. You can use functions with the onXyz properties on elements, or of course use the standard addEventListener (or attachEvent on old IE).

Upvotes: 2

Related Questions