SPFx - Creating Custom Dialog Boxes Without A Javascript Framework

In this article, we will learn how to create a custom dialog box (popup) to be displayed on a SharePoint page. First, let us start with a little background. SharePoint has an npm package that supports displaying of popup boxes on a SharePoint page.

The above npm package supports two ready-to-use Dialog boxes.

  1. To display text
  2. To display the prompt

More information can be found here.

But what if we wanted to use the same dialog framework to display custom HTML? The good news is that the Base Dialog class can be extended to create custom dialog boxes.

In this example, we will create a custom dialog box with the SPFx extension command set to display a custom dialog box. Please note that this same sample can also be used in client-side web parts. An important thing to note here is that we would be using the No JavaScript framework. If you are looking for a React-based example, please follow the official MSDN link.

Create SPFx extension command view set project

Use the below commands one by one on your node.js command prompt.

md spfx-customdialog
cd spfx-customdialog
yo @microsoft/sharepoint

Use the below options since we are creating an SPFx extension and Listview command set.

SPFx

It would take some time to generate a project. Once completed, open your project in any editor (I use VS Code).

Create a custom dialog box

Create a new file called CustomDialog.ts in the ./src/extensions/customDailogCommandSample/folder.

Add the following Import statement.

import { BaseDialog, IDialogConfiguration } from '@microsoft/sp-dialog';

Add the below class definition just after the import statement.

export default class CustomDialog extends BaseDialog {   
  public itemUrlFromExtension: string;   
  public otherParam: string;   
  public paramFromDailog: string;   
  public render(): void {   
    var html: string = "";    
    html += `<div style="padding: 10px;">`;   
    html += `<h1>Hello, I am custom Dailog Box....</h1>`;   
    html += `<p>Item Url---> <span>` + this.itemUrlFromExtension + `</span></p>`;   
    html += `<p>otherParam ---> <span>` + this.otherParam + `</span></p>`;   
    html += `<input type="text" id="inputParam">` + `</input>`;   
    html += `<br>`;   
    html += `<br>`;   
    html += `<input type="button" id="OkButton" value="Submit">`;   
    html += `</div>`;   
    this.domElement.innerHTML += html;   
    this._setButtonEventHandlers();     
  }   
  // METHOD TO BIND EVENT HANDLER TO BUTTON CLICK   
  private _setButtonEventHandlers(): void {     
    const webPart: CustomDialog = this;     
    this.domElement.querySelector('#OkButton').addEventListener('click', () => {     
      this.paramFromDailog = document.getElementById("inputParam")["value"];    
      this.close();   
    });    
  }     
  public getConfig(): IDialogConfiguration {   
    return {   
      isBlocking: false   
    };   
  }     
  protected onAfterClose(): void {   
    super.onAfterClose();        
  }   
}   

As you see here, we have created 3 variables. This is to demonstrate how we can pass data from the Extension to the Dialog box and from the Dialog box to the Extension (after it is closed).

  • itemUrlFromExtension: This variable would hold the current selected item URL which we will pass from the command set to the Dialog box.
  • otherParam: This variable would hold any other data that we can pass from the command set to the Dialog box.
  • paramFromDailog: This variable would hold any data that we will pass from the Dialog box to the command set extension (for example - taking input from the user).

Now, we have our custom dialog box definition ready to use. The next step is to call the Dialog box in the Command Set extension.

Open your extension *.ts file (mine is CustomDailogCommandSampleCommandSet.ts).

Import the custom dialog box by adding the below import statement.

import CustomDialog from './CustomDialog';

Go to the onExecute method and replace its code with the following one.

@override
public onExecute(event: IListViewCommandSetExecuteEventParameters): void {
  switch (event.itemId) {
    case 'COMMAND_1':
      const dialog: CustomDialog = new CustomDialog();
      dialog.itemUrlFromExtension = event.selectedRows[0].getValueByName("FileRef");
      dialog.otherParam = "This is parameter passed from Extension";
      dialog.show().then(() => {
        Dialog.alert(`Message from Custom Dialog --> ` + dialog.paramFromDialog);
      });
      break;
    case 'COMMAND_2':
      Dialog.alert(`${this.properties.sampleTextTwo}`);
      break;
    default:
      throw new Error('Unknown command');
  }
}

Let us understand what the above code means and what it will do. As this is the default extension created by Yeoman, we can see that there are 2 commands. We have modified COMMAND_1 which is visible only in context when an item is selected in View.

The first thing in the switch case of COMMAND_1 is to create an object of CustomDailog and set its parameters which need to be passed to the Dialog box. If you see below, we are reading Item using the event method by using the selected rows object to get FileRef (this will give us the relative path of the document). Set otherParam.

dialog.itemUrlFromExtension = event.selectedRows[0].getValueByName("FileRef");
dialog.otherParam = "This is parameter passed from Extension";

Note. If you want to access any other property or values of the selected row, log the event.selectedRows method and we can find what all properties are available.

The next thing we are doing is calling the dialog show method and using the promise method which will execute code once the Custom Dialog box is closed. Here, we are showing the default Dialog. alert method to display parameters passed from Custom Dialog.

dialog.show().then(() => {
    Dialog.alert(`Message from Custom Dialog --> ` + dialog.paramFromDailog);
});

All our code is set. Let us test out how all the pieces will work together.

Go to '/Config/serve.json' - Update page URL property to set it to any Document Library View's URL.

For example. I have set it to https://marvel.sharepoint.com/sites/avengers/salaryslips/Forms/AllItems.aspx

Open the node.js command prompt, go to the project directory, and run the 'gulp serve' command.

It will open the Document Library View.

  1. Select any document row.
  2. Click on Command view.
  3. Enter any value in the text box.
  4. Click on the "Submit" button.

Below is the output.

Output

Alert

If you see, all the values passed to/from the extension/custom dialog are being passed and printed correctly.

Conclusion

In this article, we have implemented the below use cases.

  • Creating a Custom Dialog box extending base Dialog box class
  • Custom Dialog box with No Javascript framework(to keep it simple)
  • Reading values of a selected item in extension
  • Passing data from the extension to a custom dialog box.
  • Getting input from the user in the Custom dialog box
  • Passing data back to the extension code from the custom dialog box.

I have attached only the CustomDailog.ts file and CustomDailogCommandSampleCommandSet.ts for quick reference.

Thanks for reading!!! Happy Coding!!!