How to remove an event listener that uses "this" in TypeScript?

In JavaScript for an event handler that needs access to private members and functions, I can rely on the scope of functions of those that will be available in my event handler function and do something like this:

theElement.addEventListener("click", onClick); 

and later:

 theElement.removeEventListener("click", onClick); 

In TypeScript, I need to use an anonymous function so that this an containing object, for example:

 theElement.addEventListener("click", (event) => this.onClick(event)); 

In this case, I cannot remove the anonymous function from listening to the event. How do I have an event listener as part of a class (with access to private fields and methods) that I can delete later?

+14
source share
3 answers

First, JavaScript and TypeScript behave exactly the same, even if you write like this:

 theElement.addEventListener("click", onClick); 

Secondly, here is how you can save a link to an anonymous function:

 var f = (event) => this.onClick(event); theElement.addEventListener("click", f); // later theElement.removeEventListener("click", f); 

If you are dealing with event listeners, there is a useful template for your class methods:

 class MyClass { init(theElement) { theElement.addEventListener("click", this.onClick); theElement.addEventListener("click", this.onClick2); } print() { console.log("print"); } onClick() { this.print() // possible error ('this' is not guaranteed to be MyClass) } onClick2 = () => { this.print() // no error, 'this' is guaranteed to be of type MyClass } } 

Keep in mind, however, that this code will create a separate onClick2 function for each object of the MyClass class. This can negatively impact memory usage if you create many instances of MyClass and rarely use their onClick listeners.

+22
source

In typewriting, it’s hard to understand what a function call is, especially when you β€œbind” it. Such as:

HTML

<a id="One"></a> <a id="Two"></a>

and some code that creates two objects

 let x = new MyClass("I am one", "One"); let y = new MyClass("and I am two", "Two"); 

with MyClass

 class MyClass { private _myInstance: string; constructor(ID: string, domID: string) { this._myInstance = ID; document.getElementById(domID).addEventListener('click', this.print.bind(this)); } public print() { console.log(this._myInstance); } } 

You will correct "I am one" when you click on the "One" element and "And I am two" when you click on the second element.

The situation is more complicated with the removal. You need to add the object variable with the binding enabled so that the my class changes to:

 class MyClass { private _myInstance: string; private _myDomID: string; private _myFunc = this.print.bind(this); constructor(ID: string, domID: string) { this._myInstance = ID; this._myDomID = domID; document.getElementById(domID).addEventListener('click', this._myFunc); } public print() { console.log(this._myInstance); } public cleanUp() { document.getElementById(this._myDomID).removeEventListener('click', this._myFunc); } 

}

+2
source

They have already answered the question, but the IMO answers here are not very well developed regarding OOP. So here is my solution:

 export class MyClass { // create member that holds the function reference protected clickEventListener: EventListener; // inject the Element constructor(protected theElement: Element) { // wrap the class function 'onClick' in an arrow function and assign // to the class member 'clickEventListener' this.clickEventListener = () => this.onClick(); } onClick() { console.log("clicked"); } init() { // add the event listener to 'theElement' and pass only the reference // of 'this.clickEventListener' (no round brackets '()') this.theElement.addEventListener("click", this.clickEventListener); } destroy() { // to remve the event listener also just pass the 'clickEventListener' reference this.theElement.removeEventListener("click", this.clickEventListener); } } 
+1
source

All Articles