teduniq
teduniq

Reputation: 77

How to pass "this" and another variable in EventListener?

I have a function in my addEventListener (#btn-1) that I want to remove eventually. I know that saving the function to a variable is the way to do it, but passing the "this" won't work unless it's wrapped in a function, which in turn won't be able to be removed now because it's either an anonymous function or it's not a reference to the same function even if it's named. Is there any way to do this?

const anonFunction = function(dis, str) {
  console.log(dis);
  console.log(str);
}

const myFn = function() {
  anonFunction(this, 'hello world');
}

document.querySelector('#btn-1').addEventListener('click', function() {
  anonFunction(this, 'hello world');
});

document.querySelector('#btn-2').addEventListener('click', function() {
  // doesn't work
  document.querySelector('#btn-1').removeEventListener('click', anonFunction);
});
<button id="btn-1" type="button">Call Function</button>
<button id="btn-2" type="button">Remove Event Listener</button>

UPDATE: SOLVED

Making another function calling the main function assigned to a variable and having that as the function to insert on adding and removing event listeners worked.

const anonFunction = function(dis, str) {
  console.log(dis);
  console.log(str);
}

const myFn = function() {
  anonFunction(this, 'hello world');
}

document.querySelector('#btn-1').addEventListener('click', myFn);

document.querySelector('#btn-2').addEventListener('click', function() {
  document.querySelector('#btn-1').removeEventListener('click', myFn);
});
<button id="btn-1" type="button">Call Function</button>
<button id="btn-2" type="button">Remove Event Listener</button>

Upvotes: 2

Views: 470

Answers (2)

zer00ne
zer00ne

Reputation: 43870

If you name your functions and be mindful of scope you can:

  • run functions nested in event handlers
  • pass the event object and separate parameters as well
  • can removeEventListener()

By passing the Event Object:

echo(' From A ', e) 
/* Event Object ⬆️ is passed by default by all event handlers.
Commonly used variables are e, evt, and event */

We can use the .target property which always references the origin of event, or in layman's terms, the tag that the user interacted with. (ex. the <button> the user clicked, the <input> the user typed data into, the <area> the user mouseovered, etc.)

let msg = `This data was transferred from ${e.target.tagName}.${e.target.className}`
/* Reference to e.target passed from one event handler to another 
still maintains the same reference */

while e.target is reliable, there are some events that do not reference event origin in a useful way like for instance the "submit" event. A "submit" when triggered will reference the <form> as e.target not the submit <button>.

In this particular situation, this will be lost and will be undefined. At that point, we can call echo(string, e) and reestablish what this points to:

echo(text, e); // Delegated to .B

echo.call(this, ' From A ', e); // Delegated to .A

In the example when .B is clicked this is undefined and when .A is clicked, this points to .A even though both .A and .B were bound to the same event handlers.

document.querySelector('.A').addEventListener('click', named);
document.querySelector('.B').addEventListener('click', named);

function named(e) {
  if (this.matches('.B')) {
    const text = this.textContent;
    echo(text, e);
  }
  if (this.matches('.A')) {
    echo.call(this, ' From A ', e);
  }
}

function echo(string, e) {
  let msg = `This data was transferred from ${e.target.tagName}.${e.target.className}
  ECHO: ${string.repeat(12)}
  Who is this? ${this.className}`;
  document.querySelector('.X').value = msg;
}

document.querySelector('.C').addEventListener('click', unbind);

function unbind(e) {
  document.querySelector('.A').removeEventListener('click', named);
}
<button class='A' type="button">A</button>
<button class='B' type="button">B</button>
<textarea class='X' rows='5' cols='50'></textarea>
<button class='C' type="button">C - Click to Unbind A &amp; B</button>

Upvotes: 1

Barmar
Barmar

Reputation: 780724

Just name your function that uses this.

const anonFunction = function(dis, str) {
  console.log(dis);
  console.log(str);
}

const listener = function() {
  anonFunction(this, 'hello world');
};

document.querySelector('#btn-1').addEventListener('click', listener);

document.querySelector('#btn-2').addEventListener('click', function() {
  // doesn't work
  document.querySelector('#btn-1').removeEventListener('click', listener);
});
<button id="btn-1" type="button">Call Function</button>
<button id="btn-2" type="button">Remove Event Listener</button>

Upvotes: 3

Related Questions