Creating an event listener with custom parameters?

So there was a question a few minutes ago, but by the time I’d formulated an answer on my phone, the question had been deleted. Which was too bad, because it’s a great and very common question. So, for those who would like, I’m sharing my answer anyway!

Oooooo this is a GREAT question, and a surprisingly common one. How can we have an event handler function, defined outside of our event listener, but aware of variables defined within the scope of that event listener? Sounds tricky. And it can be, but it is do-able.

First thing to understand is the concept of a closure. When we run a function, it creates a local scope, accessible to that function and any function defined within it. And if we define and return a function within another, then that returned function continues to have access to that outer functions scope, even after it has ended.

Here’s an example:

function compare(a){
  return function(b){
    // this can see it's own b, but also the a
    //  in the outer function. Even after it's
    //  been returned!
    return a===b;
  }
}

// this variable holds the function that
//  compare returned.
const compareToBob = compare("Bob");

// and it has access to both internal variables
console.log(compareToBob("Robert") )

This is all great, but why does it matter? How would this apply to your question? Why is this boomer nattering on??:grin:

Simply put, what if you define a function that takes in whatever parameters you like… and returns an event handler function? That handler is defined in the scope of the thing that created it, so it has all the parameters you like!

const makeHandlerWithParams = (id, name) => {
  return function(event){
    // but here, we have our event, id and name!
  }
}

// later, in our event listener...
myEditBtn.addEventListener("click", makeHandlerWithParams(4, "Robert") );

In that last line, our function runs immediately, and the returned result becomes the listener’s handler. With those parameters we passed in!

I’ll likely expand on this in a freecodecamp news post over the next few days, but try it out! Learn by breaking things!

Yup, that’s a common and useful pattern, a form of currying. Cool.

1 Like

You can also use bind to supply arguments to the handler.

const btn = document.querySelector("button");

function handler(...args) {
  args.forEach((arg) => console.log(arg)); // arg1, arg2, PointerEvent
}

btn.addEventListener("click", handler.bind(null, "arg1", "arg2"));
2 Likes

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.