Necesito pasar dinámicamente un nombre de función que se agregará como un controlador de eventos onclick como parte de un creador de interfaz de usuario dinámica. La mayor parte de la función es fácil, pero no puedo averiguar cómo convertir el nombre de la función de cadena en la función que está vinculada al controlador de eventos.
He intentado cosas como:
// Add event handlers Object.keys(compToAdd.events).forEach( (type) => { newEl.addEventListener( type, Function.prototype.bind( compToAdd.events[type] ) ) })Pero eso no funciona.
También probé:
window.mycb = function() { console.log('>>>> hello >>>>') } // ... Object.keys(compToAdd.events).forEach( (type) => { newEl.addEventListener( type, window['mycb'] ) }) El uso window['mycb']() ejecuta inmediatamente fn cuando se aplica al detector de eventos, lo que obviamente no es correcto. Sin () , no sucede nada cuando se activa el evento de clic.
Un enfoque más simple y posiblemente el mejor sería cargar todas sus funciones de devolución de llamada en un solo objeto, en lugar de crearlas en un alcance global:
const compToAdd = { events: { click: "onClick", mousedown: "onMouseDown", mouseup: "onMouseUp", } } const myCallbacks = { onClick: function(e) { console.log("onClick type:", e.type) }, onMouseDown: function(e) { console.log("onMouseDown type:", e.type) }, onMouseUp: "this is not a function" } // ... Object.keys(compToAdd.events).forEach( (type) => { const callback = myCallbacks[compToAdd.events[type]]; if (callback instanceof Function) //make sure it's a function newEl.addEventListener( type, callback ) }) <div id="newEl" style="height: 100vh">click here</div> PD: tu segundo ejemplo funciona bien. Si se ejecutó sin () , significa que algo desencadenó el evento.
He logrado encontrar un par de posibles respuestas. Sin embargo, no sé si me gusta ninguno de los dos y estoy seguro de que hay mejores.
eval // Add event handlers Object.keys(compToAdd.events).forEach( (type) => { // Add the event listener - hate eval but it is the only way I can get it to work try { newEl.addEventListener( type, (evt) => { eval(`${compToAdd.events[type]}(evt)`) } ) } catch (err) { console.error(`Add event '${type}' for element '${compToAdd.type}': Cannot add event handler. ${err.message}`) } })setAttribute en lugar de addEventListener // Add event handlers Object.keys(compToAdd.events).forEach( (type) => { if (type.toLowerCase === 'onclick' || type.toLowerCase === 'click') type = 'click' // Add the event listener try { newEl.setAttribute( type, `${compToAdd.events[type]}()` ) } catch (err) { console.error(`Add event '${type}' for element '${compToAdd.type}': Cannot add event handler. ${err.message}`) } })Prefiero (1) ya que parece un poco más flexible y permite el uso de funciones predefinidas en cualquier contexto accesible desde el contexto al configurar el detector de eventos. Pero está lejos de ser ideal.