Brent
Brent

Reputation: 825

Add callback to .addEventListener

Suppose I have this straightforward event listener registration pattern:

 function registerElement(){
     var element = document.getElementById("element");
     element.addEventListener("click", sayHello, false);
 }

 function sayHello(event){
     event.preventDefault();
     console.log("Hello from " + this.id);
 }

 registerElement();

Now, I'd like to add a callback function, say registerElement(callback). The idea is to execute some function after "element" gets a click, and the pseudocode might look something like this:

 function registerElement(callback){
     var element = document.getElementById("element");
     element.addEventListener("click", sayHello, false); //<--not sure what to do here to add callback to sayHello
 }

 function sayHello(event, callback){
     event.preventDefault();
     console.log("Hello from " + this.id);
     callback;
 }

 function cleanup(){
     console.log("Hello from cleanup");
 }

 registerElement(cleanup);

I'm trying to avoid using an anonymous function in registerElement to make sayHello() more reusable. I looked at bind, but that seems to focus on controlling which "this" gets sent over to the event listener function. Any other ideas?

Thanks for tips!

Upvotes: 0

Views: 4708

Answers (2)

traktor
traktor

Reputation: 19301

Event listeners are executed in the order added to an element. Again, provided sayHello does nothing asynchronous that would require the cleanup callback to be be delayed and called asynchronously as well, you could just add another event listener:

function registerElement(callback){
     var element = document.getElementById("element");
     element.addEventListener("click", sayHello, false);
     element.addEventListener("click", callback, false); 
}

If cleanup is dependent on sayHello completing an aysnchronous task, the design probably needs reviewing to use promises or async/await functions.

A more generic registration function could parameterize the element id, the type of event and take an arbitrary number of callbacks, (including sayHello) as in this example:

function register( elementId, eventType, ...callbacks) {
    const element = document.getElementById( elementId);
    for( const callback of callbacks) {
        element.addEventListener( eventType, callback, false);
    }
}

// test
const sayHello = e=>console.log("hello");
const cleanup =  e=>console.log("cleanup");
register( "myButton", "click", sayHello, cleanup);
<button type"button" id="myButton">myButton</button>

Upvotes: 1

Ele
Ele

Reputation: 33726

To avoid a mix of responsibilities, a recommendation is to execute the callback function outside of the function sayHello, otherwise the function sayHello will be tied to a second param callback:

This approach is assuming that sayHello doesn't execute any async logic within it

function registerElement(callback){
   var element = document.getElementById("element");
   element.addEventListener("click", function(e) {    
      sayHello(e);
      callback();
   }, false);
}

Upvotes: 1

Related Questions