Reputation: 22934
I asked this question a while ago about delegating jquery events to event handler methods in a typescript class. The answer was to use the following pattern
public class LoginDialog {
...
constructor() {
//this.open = this.OpenHandler; //Incorrect way
this.open = (event: Event, ui: DialogUIParams) => { //Correct way
this.OpenHandler(this, event, ui);
};
...
}
public OpenHandler(context: LoginDialog, event: Event, ui: DialogUIParams) {
//Use context as "this"
}
...
}
However, now I'm at a similar situation where I need to remove the handler at some time in the future but am unable to because of the anonymous function:
public class LoginDialog {
...
constructor() {
this.open = (event: Event, ui: DialogUIParams) => {
this.OpenHandler(this, event, ui);
};
this.close = (event: Event, ui: DialogUIParams) => {
this.CloseHandler(this, event, ui);
}
...
}
public OpenHandler(context: LoginDialog, event: Event, ui: DialogUIParams) {
$(window).on("scroll", () => { context.ScrollHandler(context); });
//$(window).on("scroll", context.ScrollHandler(context)); //Never gets called
//$(window).on("scroll", context.ScrollHandler); //this = window
}
public CloseHandler(context: LoginDialog, event: Event, ui: DialogUIParams) {
$(window).off("scroll", () => { context.ScrollHandler(context); }); //Does not remove
}
public ScrollHandler(context: Interfaces.IBaseDialog) {
context.jQueryDialog.dialog("option", "position", "center");
...
}
...
}
In this case without the arrow syntax in the on
binding, my ResizeOrScrollHandler
never get's called, but with it I'm unable to remove the event handler in the CloseHandler
Upvotes: 4
Views: 10184
Reputation: 60041
To summarize your problem, you're trying to use jQuery to hook (and unhook) an event on a DOM element, but you want the event handler's 'this' context to point to the class containing the event handler.
There are multiple ways to solve this.
First, you can use jQuery.proxy
class LoginDialog {
public OpenHandler(context: LoginDialog, event: Event, ui: DialogUIParams) {
$(window).on("scroll", $.proxy(context.ScrollHandler, context));
}
public CloseHandler(context: LoginDialog, event: Event, ui: DialogUIParams) {
$(window).off("scroll", context.ScrollHandler);
}
}
Another option would be to use RxJS, which allows you to treat events like disposable objects:
var scrollSubscription = $(window)
.onAsObservable("scroll")
.subscribe(() => console.log("this == the containing class!"));
...
// When we're done, just call .dispose.
scrollSubscription.dispose();
Have fun.
Upvotes: 6