1

How can you set an event listener to a control with a string variable name instead of function argument name?

//working method
var elementValue = document.createElement("button");
elementValue.className = "locatorTrainButton";
elementValue.addEventListener('click', myFunctionName_OnClick);

//set event from variable name
var stringName = "myFunctionName_OnClick";
elementValue.addEventListener('click', *stringName??*);
Jaume
  • 3,672
  • 19
  • 60
  • 119
  • It has to be a function, otherwise you get `Uncaught TypeError: Failed to execute 'addEventListener' on 'EventTarget': parameter 2 is not of type 'Object'.` – CertainPerformance Jan 07 '21 at 23:48
  • Take a look at: ["Variable" variables in Javascript?](https://stackoverflow.com/q/5187530), it might give you an idea how you might use a string as an object key, and a function as a value which you can then use as the second argument – Nick Parsons Jan 07 '21 at 23:59

3 Answers3

2

As long as your function is defined at the top level then you can do like:

function test(){
  console.log('worked');
}
addEventListener('click', window['test']);
Just click the window!

If your function is nested then you can assign it to window, just make sure your calls are below assignment when using function variable declaration:

(()=>{
window.test = ()=>{
  console.log('worked');
}
})();
(()=>{
addEventListener('click', window['test']);
})();
Just click the window!
StackSlave
  • 10,613
  • 2
  • 18
  • 35
1

You can't, because the listener must be an object or a function

From MDN

addEventListener() works by adding a function or an object that implements EventListener to the list of event listeners for the specified event type on the EventTarget on which it's called.

Here is the syntax:

target.addEventListener(type, listener [, options]);

target.addEventListener(type, listener [, useCapture]);

Where listener is:

The object that receives a notification (an object that implements the Event interface) when an event of the specified type occurs. This must be an object implementing the EventListener interface, or a JavaScript function.

dippas
  • 58,591
  • 15
  • 114
  • 126
  • Thank you. Ok that has to be a function or an object, but isn't there a method to relate the object with its name as a variable? So, var listener = objectFromStringName(name); elementValue.addEventListener('click', listener); – Jaume Jan 08 '21 at 00:00
  • AFAIK it is not possible unless you use `eval` (which is already answered) – dippas Jan 08 '21 at 00:05
  • The window['name'] works for me in this case. Thank you for the detailed explanation and workaround – Jaume Jan 08 '21 at 00:09
1

You cannot use a string name as a function reference in the callback. However, using an anonymous function with eval() may work, although not recommended.

That is because technically speaking you can use eval() to invoke a function by its name and then use <functionName>.apply(null, arguments) to call it with the same arguments the callback receives.

However, I would not recommend this solution because eval() in general is frowned upon as it presents security risks. Is there a reason why you want to use a dynamic function name?

function myFunctionName_OnClick(e) {
  console.log('clicked');
  
  // Verify that event is passed correctly
  console.log(e.target);
}

var elementValue = document.createElement("button");
elementValue.innerText = 'Click me!';

var stringName = "myFunctionName_OnClick";
elementValue.addEventListener('click', function() {
  eval(stringName + '.apply(null, arguments)');
});

document.body.appendChild(elementValue);
Terry
  • 63,248
  • 15
  • 96
  • 118
  • this is still a function in the listener – dippas Jan 07 '21 at 23:57
  • @dippas Yes, that is unfortunately the case. – Terry Jan 08 '21 at 00:00
  • Yes, the reason is that I am defining the controls dynamically with a general function for a code optimization. So the different controls must point into different event functions. eval() works too, beside the risks. Thanks – Jaume Jan 08 '21 at 00:14