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 which 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 Base Dialog class can be extended to create custom dialog boxes.
In this example, we will create a custom dialog box with 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 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. 
  1. md spfx-customdialog  
  2. cd spfx-customdialog   
  3. yo @microsoft/sharepoint  
Use the below options since we are creating SPFx extension and Listview command set.
SPFx - Creating Custom Dialogs Boxes No Javascript Framework
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.
  1. import { BaseDialog, IDialogConfiguration } from '@microsoft/sp-dialog';  
Add the below class defintion just after the import statement.
  1. export default class CustomDialog extends BaseDialog {  
  2.   public itemUrlFromExtension: string;  
  3.   public otherParam: string;  
  4.   public paramFromDailog:string;  
  7.   public render(): void {  
  8.       var html:string = "";  
  10.       html +=  `<div style="padding: 10px;">`;  
  11.       html+=  `<h1>Hello, I am custom Dailog Box....</h1>`;  
  12.       html+=  `<p>Item Url---> <span>` + this.itemUrlFromExtension + `</span></p>`;  
  13.       html +=  `<p>otherParam ---> <span>` + this.otherParam + `</span></p>`;  
  14.       html +=  `<input type="text" id="inputParam">` + `</input>`;  
  15.       html +=  `<br>`;  
  16.       html +=  `<br>`;  
  17.       html +=  `<input type="button" id="OkButton"  value="Submit">`;  
  18.       html +=  `</div>`;  
  19.       this.domElement.innerHTML += html;  
  20.       this._setButtonEventHandlers();    
  21.   }  
  24. rivate _setButtonEventHandlers(): void {    
  25. const webPart: CustomDialog = this;    
  26. this.domElement.querySelector('#OkButton').addEventListener('click', () => {    
  27.            this.paramFromDailog =  document.getElementById("inputParam")["value"] ;   
  28.            this.close();  
  29.  });   
  31.   public getConfig(): IDialogConfiguration {  
  32.     return {  
  33.       isBlocking: false  
  34.     };  
  35.   }  
  37.   protected onAfterClose(): void {  
  38.     super.onAfterClose();       
  39.   }  
  41. }  
If you see here, we have created 3 variables. This is to demonstrate how we can pass data from Extension to the Dialog box and from 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 which we can pass from the command set to the Dialog box.
  • paramFromDailog - This variable would hold any data which we will pass from the Dialog box to 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 custom dialog box by adding the below import statement.
  1. import CustomDialog from './CustomDialog';  
Go to the onExecute method and replace its code with the following one. 
  1. @override  
  2. public onExecute(event: IListViewCommandSetExecuteEventParameters): void {  
  3.   switch (event.itemId) {  
  4.     case 'COMMAND_1':  
  5.             const dialog: CustomDialog = new CustomDialog();  
  6.             dialog.itemUrlFromExtension = event.selectedRows[0].getValueByName("FileRef");  
  7.             dialog.otherParam = "This is parameter passed from Extension"  
  9.             dialog.show().then(() => {  
  10.               Dialog.alert(`Message from Custom Dailog-->` + dialog.paramFromDailog);  
  11.             });  
  12.       break;  
  13.     case 'COMMAND_2':  
  14.       Dialog.alert(`${this.properties.sampleTextTwo}`);  
  15.       break;  
  16.     default:  
  17.       throw new Error('Unknown command');  
  18.   }  
  19. }  
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 event method by using the selectedRows object to get FileRef (this will give us the relative path of the document). Set otherParam.
  1. dialog.itemUrlFromExtension = event.selectedRows[0].getValueByName("FileRef");  
  2. dialog.otherParam = "This is parameter passed from Extension"  
If you want to access any other property or values of selectedRow, log the event.selectedRows method and we can find what all properties are available.
The next thing we are doing is calling dialog show method and using 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.
  1. dialog.show().then(() => {      
  2.               Dialog.alert(`Message from Custom Dailog-->` + dialog.paramFromDailog);      
  3.             });    
All our code is set. Let us test it out how all the pieces will work together.
Go to  '/Config/serve.json' - Update pageUrl 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 node.js command prompt, go to the project directory, and run '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.
SPFx - Creating Custom Dialogs Boxes No Javascript Framework
SPFx - Creating Custom Dialogs Boxes No Javascript Framework
If you see, all the values passed to/from extension/custom dialog are being passed and printed correctly. 


In this article, we have implemented the below use cases.
  • Creating 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 extension to a custom dialog box.
  • Getting input from user in Custom dialog box
  • Passing data back to extension code from the custom dialog box.
I have attached only CustomDailog.ts file and CustomDailogCommandSampleCommandSet.ts for quick reference. 
Thanks for reading!!! Happy Coding!!!