This is a jquery interface from jquery.d.ts:
export interface IDialogEvent extends DialogEvent {
(event: Event, ui: DialogUIParams): void;
}
This is my custom interface mimicking partial functionality of the DialogOptions interface of jquery.d.ts:
export interface IDialogOptions {
open: IDialogEvent;
}
export class DialogClass implements IDialogOptions {
//Dialog options
public open: IDialogEvent;
//Class related fields
public someField: any;
public dialogEl: JQuery;
constructor() {
this.open = this.OpenHandler;
this.dialogEl = $("<div></div>").dialog(this);
//Passing "this" initializes the dialog by mapping relevant class fields
//to the dialog's "option" object, in this case the only "relevant" field is "open".
}
public OpenHandler(event: Event, ui: DialogUIParams) {
var value = this.someField; //BAD. "this" is not type BaseClass
}
public NonEventHandlerMethod() {
var value = this.someField; //GOOD. "this" is type BaseClass
}
}
var dialog = new DialogClass();
dialog.dialogEl.dialog("open");
The last line fires OpenHandler()
but inside it, this
is not type BaseDialog
(unlike in NonEventHandlerMethod
).
The reason I need an event handler function for the dialog options field and the reason why I can't simply do this:
export class DialogClass implements IDialogOptions {
...
constructor() {
this.open = () => {
//event handling logic
};
...
}
...
}
is because I need to add additional open-event handling logic in classes that extend DialogClass and there is no differentiation between this.member and super.member... there is only differentiation between this.function() and super.function():
export class LoginDialog extends DialogClass {
...
constructor() {
this.open = this.OpenHandler;
...
}
public OpenHandler(event: Event, ui: DialogUIParams) {
super.OpenHandler(); //Base handling logic
//Additional handling logic
}
...
}
I think this may be a bug because
export class DialogClass implements IDialogOptions {
...
constructor() {
this.open = () => {
var test = this.someField; //Correct context
};
...
}
...
}
and calling the method directly:
var dialog = new DialogClass();
dialog.OpenHandler(); //Correct context when called directly
//Note: I haven't actually tested this persay but this function is no different
//than any other functionso a direct call should certainly not be problem.
TypeScript follows the usual JavaScript scoping conventions, so this
will be dependent on context. If you have a method on a class that fires based on an event, this
will be the event target. When you directly call a method on a class, this
will be the class.
If you want to get around this, you can take advantage of how JavaScript walks up the scope chain by giving this
an alias...
Here is one way to do that:
this.open = () => { this.OpenHandler(this); };
The arrow-function syntax creates and alias name _this
in the JavaScript.
public OpenHandler(context: DialogClass, event: Event, ui: DialogUIParams) {
var value = context.someField;
}
We accept the cleverly aliased version of this
as a parameter and context.someField
should have the value we are after.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With