Dynamic Multi Selection Checkbox In SharePoint Framework (SPFx)

This blogs explains the step by step procedure to create a multi select checkbox using Sharepoint framework client side webpart (SPFx). I am using "Office UI Fabric React" controls to style the buttons. The values are stored as a semicolon separated in SharePoint list.

Code Usage
 
I have created a React component and named it as "Dialog.tsx" as shown below.
 
Import the below node modules to your solution. Here, I have used UrlQueryParameterCollection to retrieve the ListItemId which is passed as a querystring parameter. 
  1. import * as React from 'react';    
  2. import { ISpFxRichTextEditorProps } from '../ISpFxRichTextEditorProps';    
  3. import { PrimaryButton, DefaultButton, DialogType, Dialog, DialogFooter, TextField, Label } from 'office-ui-fabric-react';    
  4. import * as $ from "jquery";    
  5. import { UrlQueryParameterCollection } from '@microsoft/sp-core-library';     
Declare the state variables as shown below.
  1. export interface IDialogState {    
  2.       hideDialog: boolean;    
  3.       spanID:string;    
  4.       dialogID: string;    
  5.       standard:string;    
  6.       isDraggable: boolean;    
  7.       typeOfWorkTemparr:any[];    
  8.       typeArr:any[];  
  9. }   
Declare global arrays to hold the value.
  1. var typeofworkarr=[];  
  2.   
  3. var multiTypeOfWorkChkBox=[];  
Bind events in constructor class as shown below
  1. public constructor(props: ISpFxRichTextEditorProps) {  
  2.   
  3.         super(props);  
  4.   
  5.         this.HandleTypeOfArray=this.HandleTypeOfArray.bind(this);  
  6.   
  7.     }  
Initiate the state variables and populate the type of work values on load.
  1. public state: IDialogState = {  
  2.     hideDialog: this.props.dialogOpen,  
  3.     isDraggable: false,  
  4.     spanID: this.props.spanID,  
  5.     dialogID: this.props.id,  
  6.     standard: this.props.standard,  
  7.     /** Type of Work Values */  
  8.     typeOfWorkTemparr: [{  
  9.         name: 'Revision',  
  10.         key: 'Revision',  
  11.         label: 'Revision',  
  12.         isChecked: false  
  13.     }, {  
  14.         name: 'Design',  
  15.         key: 'Design',  
  16.         label: 'Design',  
  17.         isChecked: false  
  18.     }, {  
  19.         name: 'Maintainence',  
  20.         key: 'Maintainence',  
  21.         label: 'Maintainence',  
  22.         isChecked: false  
  23.     }, {  
  24.         name: 'Scan Print',  
  25.         key: 'Scan Print',  
  26.         label: 'Scan Print',  
  27.         isChecked: false  
  28.     }, {  
  29.         name: 'Locate Print',  
  30.         key: 'Locate Print',  
  31.         label: 'Locate Print',  
  32.         isChecked: false  
  33.     }, {  
  34.         name: 'File Print On Drive',  
  35.         key: 'File Print On Drive',  
  36.         label: 'File Print On Drive',  
  37.         isChecked: false  
  38.     }, {  
  39.         name: 'Plot/Print',  
  40.         key: 'Plot/Print',  
  41.         label: 'Plot/Print',  
  42.         isChecked: false  
  43.     }],  
  44.     typeArr: []  
  45. };  
Get the values of Dialog Label and sub text label from parent component. 
  1. private labelId: string = getId('dialogLabel');  
  2. private subTextId: string = getId('subTextLabel');  
Declare the Render function as shown below
  1. public render() {  
  2.         const {  
  3.             hideDialog  
  4.         } = this.state;  
  5.         let inputchkbox;  
  6.         let inputcontrols;  
  7.         let selectBox;  
  8.         /* input control starts here*/  
  9.         if (this.state.spanID == "spnTypeOfWork") {  
  10.             inputchkbox = this.state.typeOfWorkTemparr.map((item, i) => {  
  11.                     return ( < Label key = {  
  12.                             item.key  
  13.                         } > < input type = "checkbox"  
  14.                         ref = {  
  15.                             'ref_' + i  
  16.                         }  
  17.                         id = {  
  18.                             item.name  
  19.                         }  
  20.                         name = {  
  21.                             item.name  
  22.                         }  
  23.                         onChange = {  
  24.                             this.HandleTypeOfArray  
  25.                         }  
  26.                         value = {  
  27.                             item.name  
  28.                         }  
  29.                         checked = {  
  30.                             item.isChecked  
  31.                         }  
  32.                         />   {  
  33.                             item.name  
  34.                         } < /Label>)    
  35.                     });  
  36.             }  
  37.             /* input control ends here*/  
  38.             /* select control starts here*/  
  39.             if (this.state.spanID == "spnTypeOfWork") {  
  40.                 selectBox = < div > {  
  41.                     inputchkbox  
  42.                 } < /div>;    
  43.             }  
  44.             /* select control ends here*/  
  45.             return ( < div > < Dialog hidden = {  
  46.                     hideDialog  
  47.                 }  
  48.                 onDismiss = {  
  49.                     this.closeDialog  
  50.                 }  
  51.                 dialogContentProps = {  
  52.                     {  
  53.                         type: DialogType.normal,  
  54.                         title: this.props.value,  
  55.                         subText: "",  
  56.                         styles: {  
  57.                             title: {  
  58.                                 backgroundColor: "blue",  
  59.                                 height: 10,  
  60.                                 marginBottom: 10,  
  61.                                 paddingBottom: 22  
  62.                             }  
  63.                         }  
  64.                     }  
  65.                 }  
  66.                 modalProps = {  
  67.                     {  
  68.                         titleAriaId: this.labelId,  
  69.                         subtitleAriaId: this.subTextId,  
  70.                         isBlocking: false,  
  71.                         styles: {  
  72.                             main: {  
  73.                                 height: 350,  
  74.                                 width: 500  
  75.                             }  
  76.                         },  
  77.                     }  
  78.                 } > {  
  79.                     selectBox  
  80.                 } < DialogFooter > < PrimaryButton onClick = {  
  81.                     this.saveDialog  
  82.                 }  
  83.                 text = "Save" / > < DefaultButton onClick = {  
  84.                     this.closeDialog  
  85.                 }  
  86.                 text = "Cancel" / > < /DialogFooter>   < /Dialog>   < /div>  );  
  87.         }  
Reload the container on  componemtDidMount. 
  1. /* Initiate load containers */    
  2.     
  3.     public componentDidMount(): void {    
  4.         if(this.state.spanID == "spnTypeOfWork"){    
  5.             this.ReLoadTypeOfWorkContainer();    
  6.         }           
  7.     }    
  8.     
  9.     
  10. /** Type of Area Selection Starts */    
  11.     /** Load Area container based on values */    
  12.     public ReLoadTypeOfWorkContainer() {    
  13.         try {    
  14.             let queryParms = new UrlQueryParameterCollection(window.location.href);    
  15.             let itemID: number = parseInt(queryParms.getValue("ListItemID"));    
  16.             if (itemID != null && itemID > 0) {    
  17.                 /*Set Priority values on page load*/    
  18.                 this.SetTypeofWorkOnLoad();    
  19.             } else {    
  20.                 /*Reset Type of work values based on selection*/    
  21.                 let typeofWorkArrValues = this.state.typeOfWorkTemparr    
  22.                 $.each(multiTypeOfWorkChkBox, function (index, value) {    
  23.                     typeofWorkArrValues = [];    
  24.                     typeofWorkArrValues = value;    
  25.                 });    
  26.                 this.setState({ typeOfWorkTemparr: typeofWorkArrValues });    
  27.             }    
  28.         } catch (error) {    
  29.             console.log("Error in ReLoadTypeOfWorkContainer : " + error);    
  30.         }    
  31.     }    
  32.     
  33.     
  34.     
  35.     /* Handle Type of Array section */    
  36.     public HandleTypeOfArray(event: any):void{    
  37.         try{    
  38.             if (event.target.checked == false) {    
  39.                 for (var i = 0; i < typeofworkarr.length; i++) {    
  40.                     if (typeofworkarr[i] === event.target.value) {    
  41.                         typeofworkarr.splice(i, 1);    
  42.                     }    
  43.                 }    
  44.             }    
  45.             if (event.target.checked) {    
  46.                 if (typeofworkarr.indexOf(event.target.value) == -1) {    
  47.                     typeofworkarr.push(event.target.value)    
  48.                 }    
  49.             }    
  50.             else {    
  51.                 for (var i = 0; i < typeofworkarr.length; i++) {    
  52.                     if (typeofworkarr[i] === event.target.value) {    
  53.                         typeofworkarr.splice(i, 1);    
  54.                     }    
  55.                 }    
  56.             }    
  57.             let typeofworkArr = this.state.typeOfWorkTemparr    
  58.             typeofworkArr.forEach(types => {    
  59.                 if (types.name === event.target.value) {    
  60.                     types.isChecked = event.target.checked    
  61.                 }    
  62.             })    
  63.             multiTypeOfWorkChkBox.push(typeofworkArr);    
  64.             this.setState({ typeOfWorkTemparr: typeofworkArr });    
  65.         }catch(error){    
  66.             console.log("Error in HandleTypeOfArray : " + error);    
  67.         }    
  68.     }    
  69.     
  70.     /** Type of Area Ends */    
This function is to update the checkbox selection by retrieving the previously selected checkbox data from SharePoint list.
  1. /**Set Type of work on Load */  
  2.   
  3.     private SetTypeofWorkOnLoad(): void {  
  4.   
  5.         try {  
  6.   
  7.             var finalArray=[];  
  8.   
  9.             if ($("#" + this.state.spanID).html() !== "") {  
  10.   
  11.                 var htmlstring = this.RemovedPtagString($("#" + this.state.spanID).html()).split(',');  
  12.   
  13.                 var tempPriorArr = htmlstring;  
  14.   
  15.                 let prioritArrValues = this.state.typeOfWorkTemparr  
  16.   
  17.                 $.each(prioritArrValues, function (index, item) {  
  18.   
  19.                     if (tempPriorArr.indexOf(item.name) > -1) {  
  20.   
  21.                         item.isChecked = true;                          
  22.   
  23.                     }  
  24.   
  25.                 });  
  26.   
  27.                 this.setState({ typeOfWorkTemparr: prioritArrValues });                  
  28.   
  29.             }  
  30.   
  31.         } catch (error) {  
  32.   
  33.             console.log("Error in SetValuesOnLoad : " + error);  
  34.   
  35.         }  
  36.   
  37.     }  
  38.   
  39. }  
This  function is to close the dialog window. 
  1. /*Close dialog window*/  
  2.   
  3.     private closeDialog = (): void => {  
  4.   
  5.         this.setState({ hideDialog: true });  
  6.   
  7.         this.props.onUpdate();  
  8.   
  9.     }  
Save the selected data and send it to parent callback function as shown below. 
  1. /*Save operation based on span id selection*/    
  2.     private saveDialog = (): void => {    
  3.         if(this.state.spanID == "spnTypeOfWork"){    
  4.             this.SaveTypeOfWork();    
  5.         }         
  6.     }    
  7.     
  8. /*save type of work on save button click */    
  9.     private SaveTypeOfWork(){      
  10.         try {    
  11.               let queryParms = new UrlQueryParameterCollection(window.location.href);    
  12.             let itemID: number = parseInt(queryParms.getValue("ListItemID"));    
  13.             if (itemID != null && itemID > 0) {      
  14.                     typeofworkarr = [];      
  15.                     let prioritArrValues = this.state.typeOfWorkTemparr      
  16.                     $.each(prioritArrValues, function (index, item) {      
  17.                         if (item.isChecked == true) {      
  18.                             typeofworkarr.push(item.name);      
  19.                         }    
  20.                     });    
  21.                     this.setState({ checkboxesarr: prioritArrValues });                        
  22.             }    
  23.     
  24.             let tempvariable: string = '';    
  25.             typeofworkarr.forEach(element => {      
  26.                 tempvariable = tempvariable + "<p>" + element + "</p>";    
  27.             });      
  28.             var txtValue = tempvariable.indexOf(',') == 0 ? tempvariable.substr(1) : tempvariable;      
  29.             $("#" + this.state.spanID).html(txtValue);      
  30.             this.setState({ hideDialog: true });      
  31.             this.props.onUpdate(this.props.value);      
  32.         } catch (error) {      
  33.             console.log("Error in SaveTypeOfWork" + error);      
  34.         }    
  35.     }  
Remove HTML <P> tag from  HTML string,
  1. /*Remove p tag from html string */     
  2.     
  3.     private RemovedPtagString(removedPString): string {    
  4.     
  5.         let newString;    
  6.     
  7.         try {              
  8.     
  9.           let item = removedPString.replace(/<p[^>]*>/g, "").replace(/<\/p>/g, ",");    
  10.     
  11.           item = item.replace(",,"",");    
  12.     
  13.           newString = item.indexOf(",") == 0 ? item.substring(1) : item;    
  14.     
  15.           newString = newString.slice(0, -1);    
  16.     
  17.         } catch (error) { console.log("Error in removedPtagString : " + error ); }    
  18.     
  19.         return newString;    
  20.     
  21.     }    
Using  "DialogBox.tsx" component  in parent.
 
Import "DialogBox.tsx" reusable component in your parent file as shown below. 
 
Note
I have placed the DialoBox.tsx file under ReactDialogBox folder and hence the below path.
 
If you are not using Folder structure you can directly import the child component without giving the folder name. 
  1. import DialogBox from './ReactDialogBox/DialogBox';  
Declare the state variable in your parent state as shown below. 
  1. export interface ISpFxRichTextEditorState {  
  2.       clicked: boolean;  
  3.       listName: string;  
  4.       dialogTitle: string;  
  5.       spanID: string;  
  6.       DialogId: string;  
  7.       standard:string;  
  8.       isValidArea:string;  
  9.       toolpriorityinput:string;  
  10.       Safety:string;  
  11.     }  
Declare the props in your parent props as shown below. 
  1. export interface ISpFxRichTextEditorProps {  
  2.       id?:string;  
  3.       value?:string;  
  4.       dialogOpen?:boolean;  
  5.       spanID?:string;  
  6.       listName?:string;  
  7.       standardText?:string;  
  8.       onUpdate?:any;  
  9.       standard?:string;   
  10.     }  
In the parent constructor class, declare the below state variables 
  1. constructor(props:  ISpFxRichTextEditorProps, state: ISpFxRichTextEditorState) {  
  2.     super(props);  
  3.       
  4.     this.state = {  
  5.         clicked: false,  
  6.         listName: "",  
  7.         dialogTitle: "",  
  8.         spanID: "",  
  9.         DialogId: "",  
  10.         standard:"",  
  11.         isValidArea:"",  
  12.         toolpriorityinput:"",  
  13.         Safety:""  
  14.           
  15.     };  
  16.              
  17.   }  
 Call the dialog box in your render method of parent component. 
  1. public render(){  
  2.     return (  
  3.       <div>  
  4.       <div className="width3">  
  5.           <div className="modal-area">  
  6.             <div className="modal-heading">  
  7.               <span>  
  8.                 <b>Type of Work</b>  
  9.                 {/* <span className="mandatary">*</span> */}  
  10.               </span>  
  11.               <span  
  12.                 className="add-area float-right document-icons-area "  
  13.                 onClick={() =>  
  14.                   this.handleClick(  
  15.                     "TypeWork",  
  16.                     "Select Type of Work",  
  17.                     "spnTypeOfWork",  
  18.                     "typeWorkDlgId"  
  19.                   )  
  20.                 }  
  21.               >  
  22.                 <Icon  
  23.                   iconName="CalculatorAddition"  
  24.                   className="ms-IconExample"  
  25.                 />  
  26.                 <label>Add</label>  
  27.               </span>  
  28.             </div>  
  29.             <div className="modal-adding">  
  30.               <div id="spnTypeOfWork" />  
  31.             </div>  
  32.             <div className="modal-box">  
  33.                 {this.state.clicked ? (  
  34.                   <DialogBox  
  35.                     id={this.state.DialogId}  
  36.                     value={this.state.dialogTitle}  
  37.                     dialogOpen={false}  
  38.                     onUpdate={this.onUpdate}  
  39.                     spHttpClient={this.props.spHttpClient}  
  40.                     siteUrl={this.props.siteUrl}  
  41.                     listName={this.state.listName}  
  42.                     spanID={this.state.spanID}  
  43.                     standardText={this.state.standard}  
  44.                   />  
  45.                 ) : null}  
  46.               </div>  
  47.   
  48.           </div>  
  49.         </div>  
  50.       </div>  
  51.     );      
  52.   }  
Handle click event as shown below. 
  1. /* Open dialog on click event */  
  2.   private handleClick(  
  3.     listName: string,  
  4.     dialogTitle: string,  
  5.     spanID: string,  
  6.     DlgId: string  
  7.   ): void {  
  8.     this.setState({  
  9.       clicked: true,  
  10.       listName: listName,  
  11.       dialogTitle: dialogTitle,  
  12.       spanID: spanID,  
  13.       DialogId: DlgId  
  14.     });  
  15.   }  
"onUpdate" function acts as  call back from child component to parent component, which usually transfers the data from child to parent.
 
In the below function, I am storing the selected check box values in state variable named "Safety". 
  1. /*Dialog on update function*/  
  2.   private onUpdate = dlgOutput => {  
  3.     try{  
  4.       this.setState({  
  5.         clicked: false  
  6.       });  
  7.         
  8.       this.setState({Safety:$("#spnTypeOfWork").html()});   
  9.         
  10.     }catch(error){  
  11.       console.log("Error in onUpdate function : " + error);  
  12.     }  
  13.   }  
To replace <p> tag with semicolon use the below code.
 
Eg
 
Before - <p>Test</p><p>Sample</p>
After - Test;Sample; 
  1. public ReplaceParaWithSemiColon(stringValue):string{  
  2.     try{  
  3.       if(stringValue !== ""){  
  4.         if(stringValue.indexOf('<p>') >-1 ){  
  5.           stringValue = stringValue.replace(/<p>/g, "").replace(/<\/p>/g,";");  
  6.           stringValue = stringValue.substr(0, stringValue.length - 1);  
  7.         }          
  8.       }        
  9.       return stringValue;  
  10.     }catch(error){  
  11.       console.log("Error in ReplaceParaWithSemiColon : " +  error);  
  12.     }  
  13.   }  
Complete code of a child component "DialogBox.tsx"  is depicted below
  1. import * as React from 'react';  
  2. import { ISpFxRichTextEditorProps } from '../ISpFxRichTextEditorProps';  
  3. import { PrimaryButton, DefaultButton, DialogType, Dialog, DialogFooter, TextField, Label } from 'office-ui-fabric-react';  
  4. import * as $ from "jquery";  
  5. import { UrlQueryParameterCollection } from '@microsoft/sp-core-library';  
  6.   
  7. export interface IDialogState {  
  8.     hideDialog: boolean;  
  9.     spanID:string;  
  10.     dialogID: string;  
  11.     standard:string;  
  12.     isDraggable: boolean;  
  13.     typeOfWorkTemparr:any[];  
  14.     typeArr:any[];  
  15. }  
  16.   
  17. /*Type of Work Array Global Declarations*/  
  18. var typeofworkarr=[];  
  19. var multiTypeOfWorkChkBox=[];  
  20.   
  21. export default class DialogBox extends React.Component<ISpFxRichTextEditorProps, any>  
  22. {  
  23.       
  24.     public constructor(props: ISpFxRichTextEditorProps) {  
  25.         super(props);  
  26.         this.HandleTypeOfArray=this.HandleTypeOfArray.bind(this);  
  27.     }  
  28.     
  29.     public state: IDialogState = {  
  30.         hideDialog: this.props.dialogOpen,  
  31.         isDraggable: false,  
  32.         spanID: this.props.spanID,  
  33.         dialogID: this.props.id,  
  34.         standard:this.props.standard,  
  35.         typeOfWorkTemparr:[{  
  36.             name: 'Revision',  
  37.             key: 'Revision',  
  38.             label: 'Revision',  
  39.             isChecked: false                
  40.           },  
  41.           {  
  42.             name: 'Design',  
  43.             key: 'Design',  
  44.             label: 'Design',  
  45.             isChecked: false  
  46.           },  
  47.           {  
  48.             name: 'Maintainence',  
  49.             key: 'Maintainence',  
  50.             label: 'Maintainence',  
  51.             isChecked: false               
  52.           },  
  53.           {  
  54.             name: 'Scan Print',  
  55.             key: 'Scan Print',  
  56.             label: 'Scan Print',  
  57.             isChecked: false  
  58.           },  
  59.           {  
  60.             name: 'Locate Print',  
  61.             key: 'Locate Print',  
  62.             label: 'Locate Print',  
  63.             isChecked: false  
  64.           },  
  65.           {  
  66.             name: 'File Print On Drive',  
  67.             key: 'File Print On Drive',  
  68.             label: 'File Print On Drive',  
  69.             isChecked: false  
  70.           },  
  71.           {  
  72.             name: 'Plot/Print',  
  73.             key: 'Plot/Print',  
  74.             label: 'Plot/Print',  
  75.             isChecked: false  
  76.           }  
  77.         ],  
  78.         typeArr :[]  
  79.     };  
  80.   
  81.       
  82.     private labelId: string = getId('dialogLabel');  
  83.     private subTextId: string = getId('subTextLabel');  
  84.       
  85.     public render() {  
  86.         const { hideDialog } = this.state;  
  87.         let inputchkbox;  
  88.         let inputcontrols;  
  89.         let selectBox;  
  90.           
  91.         /* input control ends here*/  
  92.         if (this.state.spanID == "spnTypeOfWork") {  
  93.             inputchkbox = this.state.typeOfWorkTemparr.map((item, i) => {  
  94.                 return (<Label key={item.key}>  
  95.                     <input type="checkbox" ref={'ref_' + i} id={item.name} name={item.name} onChange={this.HandleTypeOfArray} value={item.name} checked={item.isChecked} />  
  96.                     {item.name}  
  97.                 </Label>)  
  98.             });  
  99.         }  
  100.         /* input control ends here*/  
  101.   
  102.         /* select control starts here*/  
  103.         if(this.state.spanID == "spnTypeOfWork"){  
  104.             selectBox = <div>{inputchkbox}</div>;  
  105.         }  
  106.         /* select control ends here*/  
  107.   
  108.         return (  
  109.             <div>  
  110.                 <Dialog  
  111.                     hidden={hideDialog}  
  112.                     onDismiss={this.closeDialog}  
  113.                     dialogContentProps={{  
  114.                         type: DialogType.normal,  
  115.                         title: this.props.value,  
  116.                         subText: "",  
  117.                         styles: { title: { backgroundColor: "blue", height: 10, marginBottom: 10, paddingBottom: 22 } }  
  118.                     }}  
  119.                     modalProps={{  
  120.                         titleAriaId: this.labelId,  
  121.                         subtitleAriaId: this.subTextId,  
  122.                         isBlocking: false,  
  123.                         styles: { main: { height: 350, width: 500 } },  
  124.                     }}>  
  125.                     {selectBox}  
  126.                       
  127.                     <DialogFooter>  
  128.                         <PrimaryButton onClick={this.saveDialog} text="Save" />  
  129.                         <DefaultButton onClick={this.closeDialog} text="Cancel" />  
  130.                     </DialogFooter>  
  131.                 </Dialog>  
  132.             </div>  
  133.   
  134.         );  
  135.     }  
  136.     
  137.     /* Initiate load containers */  
  138.     public componentDidMount(): void {  
  139.         if(this.state.spanID == "spnTypeOfWork"){  
  140.             this.ReLoadTypeOfWorkContainer();  
  141.         }  
  142.     }  
  143.      
  144.     /** Type of Area Selection Starts */  
  145.     /** Load Area container based on values */  
  146.     public ReLoadTypeOfWorkContainer() {  
  147.         try {  
  148.             let queryParms = new UrlQueryParameterCollection(window.location.href);  
  149.             let itemID: number = parseInt(queryParms.getValue("ListItemID"));  
  150.             if (itemID != null && itemID > 0) {  
  151.                 /*Set Priority values on page load*/  
  152.                 this.SetTypeofWorkOnLoad();  
  153.             } else {  
  154.                 /*Reset Type of work values based on selection*/  
  155.                 let typeofWorkArrValues = this.state.typeOfWorkTemparr  
  156.                 $.each(multiTypeOfWorkChkBox, function (index, value) {  
  157.                     typeofWorkArrValues = [];  
  158.                     typeofWorkArrValues = value;  
  159.                 });  
  160.                 this.setState({ typeOfWorkTemparr: typeofWorkArrValues });  
  161.             }  
  162.         } catch (error) {  
  163.             console.log("Error in ReLoadTypeOfWorkContainer : " + error);  
  164.         }  
  165.     }  
  166.     /* Handle Type of Array section */  
  167.     public HandleTypeOfArray(event: any):void{  
  168.         try{  
  169.             if (event.target.checked == false) {  
  170.                 for (var i = 0; i < typeofworkarr.length; i++) {  
  171.                     if (typeofworkarr[i] === event.target.value) {  
  172.                         typeofworkarr.splice(i, 1);  
  173.                     }  
  174.                 }  
  175.             }  
  176.             if (event.target.checked) {  
  177.   
  178.                 if (typeofworkarr.indexOf(event.target.value) == -1) {  
  179.                     typeofworkarr.push(event.target.value)  
  180.                 }  
  181.             }  
  182.             else {  
  183.                 for (var i = 0; i < typeofworkarr.length; i++) {  
  184.                     if (typeofworkarr[i] === event.target.value) {  
  185.                         typeofworkarr.splice(i, 1);  
  186.                     }  
  187.                 }  
  188.             }  
  189.             let typeofworkArr = this.state.typeOfWorkTemparr  
  190.             typeofworkArr.forEach(types => {  
  191.                 if (types.name === event.target.value) {  
  192.                     types.isChecked = event.target.checked  
  193.                 }  
  194.             })  
  195.             multiTypeOfWorkChkBox.push(typeofworkArr);  
  196.             this.setState({ typeOfWorkTemparr: typeofworkArr });  
  197.         }catch(error){  
  198.             console.log("Error in HandleTypeOfArray : " + error);  
  199.         }  
  200.     }  
  201.     /** Type of Area Ends */  
  202.   
  203.     /*Close dialog window*/  
  204.     private closeDialog = (): void => {  
  205.         this.setState({ hideDialog: true });  
  206.         this.props.onUpdate();  
  207.     }  
  208.              
  209.     /*Save operation based on span id selection*/  
  210.     private saveDialog = (): void => {  
  211.         if(this.state.spanID == "spnTypeOfWork"){  
  212.             this.SaveTypeOfWork();  
  213.         }       
  214.     }  
  215.   
  216.     /*save proirity on save button click */  
  217.     private SaveTypeOfWork(){  
  218.         try {  
  219.   
  220.             let queryParms = new UrlQueryParameterCollection(window.location.href);  
  221.             let itemID: number = parseInt(queryParms.getValue("ListItemID"));  
  222.             if (itemID != null && itemID > 0) {  
  223.                     typeofworkarr = [];  
  224.                     let prioritArrValues = this.state.typeOfWorkTemparr  
  225.                     $.each(prioritArrValues, function (index, item) {  
  226.                         if (item.isChecked == true) {  
  227.                             typeofworkarr.push(item.name);  
  228.                         }  
  229.                     });  
  230.                                           
  231.             }  
  232.   
  233.             let tempvariable: string = '';  
  234.             typeofworkarr.forEach(element => {  
  235.                 tempvariable = tempvariable + "<p>" + element + "</p>";  
  236.             });  
  237.             var txtValue = tempvariable.indexOf(',') == 0 ? tempvariable.substr(1) : tempvariable;  
  238.             $("#" + this.state.spanID).html(txtValue);  
  239.             this.setState({ hideDialog: true });  
  240.             this.props.onUpdate(this.props.value);  
  241.         } catch (error) {  
  242.             console.log("Error in SaveTypeOfWork" + error);  
  243.         }  
  244.     }  
  245.   
  246.     /*Other Functions*/  
  247.     /*Remove p tag from html string */   
  248.     private RemovedPtagString(removedPString): string {  
  249.         let newString;  
  250.         try {            
  251.           let item = removedPString.replace(/<p[^>]*>/g, "").replace(/<\/p>/g, ",");  
  252.           item = item.replace(",,"",");  
  253.           newString = item.indexOf(",") == 0 ? item.substring(1) : item;  
  254.           newString = newString.slice(0, -1);  
  255.         } catch (error) { console.log("Error in removedPtagString : " + error ); }  
  256.         return newString;  
  257.     }  
  258.   
  259.     /**Set Type of work on Load */  
  260.     private SetTypeofWorkOnLoad(): void {  
  261.         try {  
  262.             var finalArray=[];  
  263.             if ($("#" + this.state.spanID).html() !== "") {  
  264.                 var htmlstring = this.RemovedPtagString($("#" + this.state.spanID).html()).split(',');  
  265.                 var tempPriorArr = htmlstring;  
  266.                 let prioritArrValues = this.state.typeOfWorkTemparr  
  267.                 $.each(prioritArrValues, function (index, item) {  
  268.                     if (tempPriorArr.indexOf(item.name) > -1) {  
  269.                         item.isChecked = true;                          
  270.                     }  
  271.                 });  
  272.                 this.setState({ typeOfWorkTemparr: prioritArrValues });                  
  273.             }  
  274.   
  275.         } catch (error) {  
  276.             console.log("Error in SetTypeofWorkOnLoad : " + error);  
  277.         }  
  278.     }     
  279.   
  280. }  
Complete code of a parent component "Parent.tsx" is depicted below,
  1. import * as React from 'react';  
  2. import { ISpFxRichTextEditorProps } from './ISpFxRichTextEditorProps';  
  3. import { ISpFxRichTextEditorState } from './ISpFxRichTextEditorState';  
  4. import { UrlQueryParameterCollection } from '@microsoft/sp-core-library';  
  5. import { css, DefaultButton, IButtonProps, IStyle, Label, PrimaryButton, DialogType, Dialog, DialogFooter, format, Icon, TextField } from 'office-ui-fabric-react';  
  6. import DialogBox from './ReactDialogBox/DialogBox';  
  7.   
  8. export default class SpFxRichTextEditor extends React.Component<ISpFxRichTextEditorProps, ISpFxRichTextEditorState> {  
  9.       
  10.   constructor(props:  ISpFxRichTextEditorProps, state: ISpFxRichTextEditorState) {  
  11.     super(props);  
  12.     this.state = {  
  13.         clicked: false,  
  14.         listName: "",  
  15.         dialogTitle: "",  
  16.         spanID: "",  
  17.         DialogId: "",  
  18.         standard:"",  
  19.         isValidArea:"",  
  20.         toolpriorityinput:"",  
  21.         Safety:""  
  22.           
  23.     };  
  24.              
  25.   }    
  26.    
  27.   /* Open dialog on click event */  
  28.   private handleClick(  
  29.     listName: string,  
  30.     dialogTitle: string,  
  31.     spanID: string,  
  32.     DlgId: string  
  33.   ): void {  
  34.     this.setState({  
  35.       clicked: true,  
  36.       listName: listName,  
  37.       dialogTitle: dialogTitle,  
  38.       spanID: spanID,  
  39.       DialogId: DlgId  
  40.     });  
  41.   }  
  42.   
  43.   public render(){  
  44.     return (  
  45.       <div>  
  46.          <div className="width3">  
  47.           <div className="modal-area">  
  48.             <div className="modal-heading">  
  49.               <span>  
  50.                 <b>Type of Work</b>  
  51.                 {/* <span className="mandatary">*</span> */}  
  52.               </span>  
  53.               <span  
  54.                 className="add-area float-right document-icons-area "  
  55.                 onClick={() =>  
  56.                   this.handleClick(  
  57.                     "TypeWork",  
  58.                     "Select Type of Work",  
  59.                     "spnTypeOfWork",  
  60.                     "typeWorkDlgId"  
  61.                   )  
  62.                 }  
  63.               >  
  64.                 <Icon  
  65.                   iconName="CalculatorAddition"  
  66.                   className="ms-IconExample"  
  67.                 />  
  68.                 <label>Add</label>  
  69.               </span>  
  70.             </div>  
  71.             <div className="modal-adding">  
  72.               <div id="spnTypeOfWork" />  
  73.             </div>  
  74.             <div className="modal-box">    
  75.                 {this.state.clicked ? (    
  76.                   <DialogBox    
  77.                     id={this.state.DialogId}    
  78.                     value={this.state.dialogTitle}    
  79.                     dialogOpen={false}    
  80.                     onUpdate={this.onUpdate}    
  81.                     spHttpClient={this.props.spHttpClient}    
  82.                     siteUrl={this.props.siteUrl}    
  83.                     listName={this.state.listName}    
  84.                     spanID={this.state.spanID}    
  85.                     standardText={this.state.standard}    
  86.                   />    
  87.                 ) : null}    
  88.               </div>    
  89.             </div>  
  90.         </div>  
  91.       </div>  
  92.     );      
  93.   }  
  94.   
  95.      
  96.   /*Dialog on update function*/  
  97.   private onUpdate = dlgOutput => {  
  98.     try{  
  99.       this.setState({  
  100.         clicked: false  
  101.       });  
  102.     
  103.       this.setState({Safety:$("#spnTypeOfWork").html()});   
  104.         
  105.     }catch(error){  
  106.       console.log("Error in onUpdate function : " + error);  
  107.     }  
  108.   }  
  109.   
  110.   /*Replace semicolon with paragraph */  
  111.   public ReplaceSemiColon(stringValue):string{  
  112.     try{  
  113.       var htmlString='';  
  114.       var temp = [];  
  115.       if(stringValue !== ""){  
  116.         if(stringValue.indexOf(';') > -1){  
  117.           temp = stringValue.split(';')  
  118.           $.each(temp,function(index,value){  
  119.             htmlString = htmlString + "<p>" + value + "</p>"  
  120.           });  
  121.             
  122.         }  
  123.       }  
  124.       return htmlString;  
  125.     }catch(error){  
  126.       console.log("Error in ReplaceSemiColon : " +  error);  
  127.     }  
  128.   }  
  129.   
  130.   /*Replace paragraph with semicolon */  
  131.   public ReplaceParaWithSemiColon(stringValue):string{  
  132.     try{  
  133.       if(stringValue !== ""){  
  134.         if(stringValue.indexOf('<p>') >-1 ){  
  135.           stringValue = stringValue.replace(/<p>/g, "").replace(/<\/p>/g,";");  
  136.           stringValue = stringValue.substr(0, stringValue.length - 1);  
  137.         }          
  138.       }        
  139.       return stringValue;  
  140.     }catch(error){  
  141.       console.log("Error in ReplaceParaWithSemiColon : " +  error);  
  142.     }  
  143.   }  
  144.   
  145. }  
Below are the sample styles used to create a multi selection check box.
 
CSS
  1. .ms-Dialog-header .ms-Dialog-title {  
  2.     background-color:#da291c;  
  3.     color#fff;  
  4.     padding8px;  
  5.     height40px;  
  6.     box-sizing: border-box;  
  7.     line-height1;  
  8.     font-weightbold;  
  9.               font-size20px;  
  10. }  
  11. .ms-Dialog-header .ms-Button {  
  12.     color#fff;  
  13.     positionrelative;  
  14.     top: -6px;  
  15.     floatright;  
  16.     right: 0px;  
  17.               min-width:0em;  
  18. }  
  19. .ms-Dialog-header .ms-Button:hover,.ms-Dialog-header .ms-Button:active, .ms-Dialog-header .ms-Button:focus  {  
  20.     backgroundnone !important;  
  21. }  
  22. .ms-Dialog-header {  
  23.     margin-right40px;  
  24. }  
  25. .modal-heading {  
  26.     border1px solid #ccc;  
  27.     padding10px;  
  28.     background#f1f1f1;  
  29. }  
  30.   
  31. .modal-adding {  
  32.     border1px solid #ccc;  
  33.     background#fff;  
  34.     padding10px;  
  35.     min-height100px;  
  36. }  
  37.   
  38. .ms-Button-flexContainer {  
  39.     floatleft;  
  40. }  
Output
 
 
 
 
Please feel free to share your comments.
 
I hope this helps!!!!!