5

Problem : I would like to call a function "test " with passing parameters using the click event of the button.

using addEventListener ('click', test ); works.

using addEventListener ('click', test(parameter)); the function is activated automatically when loading and not to click on the button .

Question: how to pass parameters ?

//create 3 button (n is a counter):
    var btn = document.createElement("INPUT");
        btn.setAttribute("id", "demo"+n);
        btn.setAttribute("type", "button");
        btn.setAttribute("value", ("click"));
        document.body.appendChild(btn);

call Without parameters works correcty:

function test(m) {
    alert("YOU CLICKED ME!");
}

var m=0;
while(m!=3){
        document.getElementById("demo"+m).addEventListener("click", test);
        m=m+1;
}   

`

with parameters not works (the function is activated immediately):

function test(m) {
    alert("YOU CLICKED ME!"+m);
}

var m=0;
while(m!=3){
    document.getElementById("demo"+m).addEventListener("click", test(m));
            m=m+1;
}   
bugwheels94
  • 30,681
  • 3
  • 39
  • 60
MrEnrich
  • 53
  • 1
  • 6

4 Answers4

5

Wrap your function in another function to avoid invoking it immediately

document.getElementById("demo"+m).addEventListener("click",(function(x){
    return function(){
        test(x);
    }
})(m));

In your case addEventListener expects a function object so you can't use parenthesis in front of function as it invokes the function and passes the returning value. So you need to return the function object which invokes test function( using an anonymous function to avoid closure property of javascript functions)

EDIT: Reason for returning wrapper function of test using an anonymous function

We can't pass

function(){
    test(m);
}

to addEventListener directly. As every function object in javascript remembers the environment( in our case variable m) outside their lexical scope . If you just create different function(like in while loop) in same environment( variable m ) then they will reference to same environment.

You have two use a function factory to avoid creating closures in loop like described above.

bugwheels94
  • 30,681
  • 3
  • 39
  • 60
2

Try this:

function test(m) {
    alert("YOU CLICKED ME!"+m);
}

var m=0;
while (m!=3) {
    (function(m) {
        document.getElementById("demo"+m).addEventListener("click", function() {
            test(m);
        });
    })(m);
    m=m+1;
}   

this will create new scope for variable inside to loop.

jcubic
  • 61,973
  • 54
  • 229
  • 402
2

Explanation about why addEventListener('click', test(parameter)) doesn't work

The addEventListener function can accept two parameters, a event type and a listener object that receives the event. In most cases, the listener object is simply a JavaScript function.

So when you use

addEventListener('click', test);

You are passing the string click as the event type, and a function test as the listener, which is what you have expected.

But when you use

addEventListener('click', test(parameter));

The listener is actually the value that the expression test(parameter) evaluates to. Since test(parameter) is a function call, you actually pass in what what is returned by test(parameter), in your case, 'undefined' since test function does not return anything. This is why test is called immediately - it need to be invoked to get the return value as a parameter of your addEventListener function call.

So to execute a function with custom parameters when the event happens, as others have suggested, you can use the anonymous function approach.

Renfei Song
  • 2,941
  • 2
  • 25
  • 30
0

You need to build versions of the test function, using what is called a "high-order function":

// this is a high order function, since it returns a function
function buildTestFunction(m) {
  return function () {
    alert("YOU CLICKED ME!"+m);
  };
}

var m=0;
while(m!=3){
  var test = buildTestFunction(m);
  document.getElementById("demo"+m).addEventListener("click", test);
  m=m+1;
}

PS. You might want to use a for loop here, for clarity.

for (var m = 0; m < 3; m++) { ... }
jgroenen
  • 1,332
  • 1
  • 8
  • 13