SPFx JQuery Dialog button click does not find public function
-
08-02-2021 - |
Question
I am new to TypeScript and SPFx development.
I have a jquery UI dialog box and a public function in the same class that makes some MSGRAPH calls after the button has been clicked.
The button click returns with error:
this.addAlert is not a function
I think the problem is that the dialog code executes outside the web part context and hence does not know about the function available in the webpart context.
How can I use the button click to run within the webpart context?
Here is the Dialog code.
public render(): void {
this.domElement.innerHTML = AlertTemplate.templateHtml;
const dialogOptions: JQueryUI.DialogOptions = {
width: "50%",
height: "auto",
buttons: {
"Subscribe": function (e) {
this.addAlert("Yes");
jQuery(this).dialog("close");
},
"No Thanks": function (e) {
console.log("moo");
this.addAlert("No");
jQuery(this).dialog("close");
},
"Ask me later": function (e) {
this.addAlert("Ask Me Later");
jQuery(this).dialog("close");
}
}
};
jQuery('.dialog', this.domElement).dialog(dialogOptions);
jQuery(".ui-dialog-titlebar").hide();
}
function addAlert
public addAlert(status: string): void {
var url = "/sites/" + this.context.pageContext.site.id + "/lists";
var listId = "";
var email = this.getCurrentUserEmail();
var recordExists = false;
let item: SubscriptionListItem;
this.context.msGraphClientFactory
.getClient()
.then((client: MSGraphClient): void => {
client
.api(url)
.top(1)
.filter("equals=(displayName, 'Subscriptions'")
.version("v1.0")
.get((err, res) => {
if (err) {
console.error(err);
return;
}
console.log(res);
listId = res.id;
});
});
Solution
The this
reference inside the context of the event handler is not a reference to your react component. this
in that context is usually the object that triggered the event, such as the clicked button. In JSX you can use binding to bind your event handler to the context of your component:
You have to be careful about the meaning of
this
in JSX callbacks. In JavaScript, class methods are not bound by default. If you forget tobind
this.handleClick
and pass it toonClick
,this
will be undefined when the function is actually called.This is not React-specific behavior; it is a part of how functions work in JavaScript. Generally, if you refer to a method without () after it, such as
onClick={this.handleClick}
, you should bind that method.
There are multiple techniques in the above referenced article for binding your event handlers to your component's this
context, but here is one example:
public onDialogButtonClick(status: string, e): void {
this.addAlert(status);
jQuery('.dialog', this.domElement).dialog("close");
}
public render(): void {
this.domElement.innerHTML = AlertTemplate.templateHtml;
const dialogOptions: JQueryUI.DialogOptions = {
width: "50%",
height: "auto",
buttons: {
"Subscribe": this.onDialogButtonClick.bind(this, "Subscribe"),
"No Thanks": this.onDialogButtonClick.bind(this, "No Thanks"),
"Ask me later": this.onDialogButtonClick.bind(this, "Ask me later")
}
};
jQuery('.dialog', this.domElement).dialog(dialogOptions);
jQuery(".ui-dialog-titlebar").hide();
}