0

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;
      });
  });

1 Answer 1

0

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 to bind this.handleClick and pass it to onClick, 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();
}
3
  • Thanks for your response. I think this would work, however, I am getting another error when I try to close the dialog cannot call methods on dialog prior to initialization; attempted to call method 'close'. Any idea as to why?
    – salli
    Commented Feb 17, 2020 at 17:44
  • nvm. Changing the code to this jQuery('.dialog', this.domElement).dialog("close");. Thanks for your help. Can you please update the code and I will accept it as the answer.
    – salli
    Commented Feb 17, 2020 at 17:54
  • I added your new close method to the code sample.
    – willman
    Commented Feb 17, 2020 at 18:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.