Customizing SharePoint Framework Web Part Properties - Part Two

Introduction 
 
In this article, you will learn how to add custom properties (check box options) to the SharePoint Framework web part.
 
In my previous article, I  introduced the custom properties on SharePoint Framework (SPFx).
In my SPFx article series, you can learn about SPFx introduction, prerequisites, steps for setting up the environment, and developing and testing the web parts using the local environments.
In this sample, you will see how to add check box options to the SPFx web part properties pane. The web part will render the items of a list with multiple columns based on the checked items.
 
The list column names are added as check box fields in the properties pane. The columns that are shown on the web part are Title, Created By, and Created Time. Title is the mandatory value shown, and we will see how to bind the other two values into web part.
 
Check box is rendered based on PropertyPaneCheckbox class. It contains three attributes. They are,
  • Text - contains the label for the check box item
  • isChecked - boolean value, used to determine whether the item is selected.
  • isEnabled - boolean value, item can be disabled or enabled.
The required interfaces are defined. The required data is imported from other files or libraries using import option. 
  1. import {  
  2.   BaseClientSideWebPart,  
  3.   IPropertyPaneSettings,  
  4.   IWebPartContext,  
  5.   PropertyPaneTextField,  
  6.   PropertyPaneCheckbox  
  7. } from '@microsoft/sp-client-preview';  
  8.   
  9. import styles from './ListItemsForm.module.scss';  
  10. import * as strings from 'listItemsFormStrings';  
  11. import { IListItemsFormWebPartProps } from './IListItemsFormWebPartProps';  
  12.   
  13. export interface spListItems{  
  14.   value: spListItem[]  
  15. }  
  16. export interface spListItem{  
  17.   Title: string;  
  18.   id: string;  
  19.   Created: string;  
  20.   Author: {  
  21.     Title: string;  
  22.   };  
  23. }   
To the existing properties page, another group is added. The group contains two check box fields.
  • Created Time
  • Author
Likewise, any number of checkboxes can be added.
 
The property text variables are initialized in the class before the constructor.
  1. private checkboxProperty1: string = "Created";  
  2. private checkboxProperty2: string = "Author";   
The properties are defined in the propertyPaneSettings method. Users can select or deselect the properties (options). The following snippet shows the method.
  1. protected get propertyPaneSettings(): IPropertyPaneSettings {  
  2.   return {  
  3.     pages: [  
  4.       {  
  5.         header: {  
  6.           description: strings.PropertyPaneDescription  
  7.         },  
  8.         groups: [  
  9.           {  
  10.             groupName: strings.BasicGroupName,  
  11.             groupFields: [  
  12.               PropertyPaneTextField('description', {  
  13.                 label: strings.DescriptionFieldLabel  
  14.               })  
  15.             ]  
  16.           },  
  17.           {  
  18.             groupName: "OptionalFields",  
  19.             groupFields: [  
  20.               PropertyPaneCheckbox('checkboxProperty1',{  
  21.                 isChecked:false,  
  22.                 isEnabled:true,  
  23.                 text: this.checkboxProperty1  
  24.               }),  
  25.               PropertyPaneCheckbox('checkboxProperty2',{  
  26.                 isChecked:false,  
  27.                 isEnabled:true,  
  28.                 text: this.checkboxProperty2  
  29.               })  
  30.             ]  
  31.           }  
  32.         ]  
  33.       }  
  34.     ]  
  35.   };  
  36. }   
Based on the check box options selected, REST API is constructed, and the items are retrieved from the list. The list items are then displayed in tabular format. Render method displays the data on the web part. The custom methods render the list items based on the properties selected. Appropriate style content is referred from the .scss file.
  1. public render(): void {  
  2.   // Render the items in tabular format  
  3.   this.domElement.innerHTML = `  
  4.     <div class="${styles.listItemsForm}">  
  5.       <div class="${styles.Table}">  
  6.         <div class="${styles.Heading}">  
  7.           <div class="${styles.Cell}">Title</div>  
  8.         </div>  
  9.       </div>  
  10.     </div>`;  
  11.   
  12.     this.listName = "TestList";  
  13.     this.LoadData();  
  14. }  
  15.   
  16. private LoadData(): void{  
  17.   
  18.   let url: string = this.context.pageContext.web.absoluteUrl + "/_api/web/lists/getbytitle('"+this.listName+"')/items?$select=Title";  
  19.   // If Created Time check box option is selected  
  20.   if(this.properties.checkboxProperty1){  
  21.     url += ",Created";  
  22.     // Column header for Created Time field  
  23.      this.domElement.querySelector("."+styles.Heading).innerHTML +=`<div class="${styles.Cell}">Created</div>`;  
  24.   }  
  25.   // If Author check box option is selected  
  26.   if(this.properties.checkboxProperty2){  
  27.     url += ",Author/Title&$expand=Author";  
  28.     // Column header for Author field  
  29.     this.domElement.querySelector("."+styles.Heading).innerHTML +=`<div class="${styles.Cell}">Author</div>`;  
  30.   }  
  31.   
  32.   this.GetListData(url).then((response)=>{  
  33.     // Render the data in the web part  
  34.     this.RenderListData(response.value);  
  35.   });  
  36. }  
  37.   
  38. private GetListData(url: string): Promise<spListItems>{  
  39.   // Retrieves data from SP list  
  40.   return this.context.httpClient.get(url).then((response: Response)=>{  
  41.      return response.json();  
  42.   });  
  43. }  
  44. private RenderListData(listItems: spListItem[]): void{  
  45.   let itemsHtml: string = "";  
  46.   // Displays the values in table rows  
  47.   listItems.forEach((listItem: spListItem)=>{  
  48.     let itemTimeStr: string = listItem.Created;  
  49.     let itemTime: Date = new Date(itemTimeStr);  
  50.     itemsHtml += `<div class="${styles.Row}">`;  
  51.     itemsHtml += `<div class="${styles.Cell}"><p>${listItem.Title}</p></div>`;  
  52.     if(this.properties.checkboxProperty1){  
  53.       itemsHtml += `<div class="${styles.Cell}"><p>${listItem.Created}</p></div>`;  
  54.     }  
  55.     if(this.properties.checkboxProperty2){  
  56.       itemsHtml += `<div class="${styles.Cell}"><p>${listItem.Author.Title}</p></div>`;  
  57.     }  
  58.   
  59.     itemsHtml += `</div>`;  
  60.   });  
  61.   this.domElement.querySelector("."+styles.Table).innerHTML +=itemsHtml;  
  62. }   
For example, this.properties.checkboxProperty1 gives the boolean value for the first check box option ("Created Time" column). The following snapshot shows the list items displayed based on the check box.
 
The below snapshot shows the list items without "Created Time" column.
 

NoteThe web part can be deployed to the site and added to the page. In my previous article, you can see the steps for deployment. 
 
Entire Code
 
The changes made to the different files are shown in the following code snippets.
 
IListItemsFormWebPartProps.ts File
  1. export interface IListItemsFormWebPartProps {  
  2.   description: string;  
  3.   checkboxProperty1: string;  
  4.   checkboxProperty2: string;  
  5. }  
ListItemsForm.module.scss File 
  1. .listItemsForm {  
  2.   .container {  
  3.     max-width: 700px;  
  4.     margin: 0px auto;  
  5.     box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2), 0 25px 50px 0 rgba(0, 0, 0, 0.1);  
  6.   }  
  7.   
  8.   .row {  
  9.     padding: 20px;  
  10.   }  
  11.   
  12.   .listItem {  
  13.     max-width: 715px;  
  14.     margin: 5px auto 5px auto;  
  15.     box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.2), 0 25px 50px 0 rgba(0, 0, 0, 0.1);  
  16.   }  
  17.   
  18.   .button {  
  19.     text-decoration: none;  
  20.   }  
  21.   .listItemTitle{  
  22.     font-size: large;  
  23.     color: darkblue;  
  24.   }  
  25.   .listItemProps{  
  26.     font-size: small;  
  27.   }  
  28.   
  29.   .Table  
  30.     {  
  31.         display: table;  
  32.     }  
  33.     .Title  
  34.     {  
  35.         display: table-caption;  
  36.         text-align: center;  
  37.         font-weight: bold;  
  38.         font-size: larger;  
  39.     }  
  40.     .Heading  
  41.     {  
  42.         display: table-row;  
  43.         font-weight: bold;  
  44.         text-align: center;  
  45.     }  
  46.     .Row  
  47.     {  
  48.         display: table-row;  
  49.     }  
  50.     .Cell  
  51.     {  
  52.         display: table-cell;  
  53.         border: solid;  
  54.         border-width: thin;  
  55.         padding-left: 5px;  
  56.         padding-right: 5px;  
  57.     }  
  58. }  
ListItemsFormWebPart.ts File
  1. import {  
  2.   BaseClientSideWebPart,  
  3.   IPropertyPaneSettings,  
  4.   IWebPartContext,  
  5.   PropertyPaneTextField,  
  6.   PropertyPaneCheckbox  
  7. } from '@microsoft/sp-client-preview';  
  8.   
  9. import styles from './ListItemsForm.module.scss';  
  10. import * as strings from 'listItemsFormStrings';  
  11. import { IListItemsFormWebPartProps } from './IListItemsFormWebPartProps';  
  12.   
  13. export interface spListItems{  
  14.   value: spListItem[]  
  15. }  
  16. export interface spListItem{  
  17.   Title: string;  
  18.   id: string;  
  19.   Created: string;  
  20.   Author: {  
  21.     Title: string;  
  22.   };  
  23. }  
  24.   
  25.   
  26. export default class ListItemsFormWebPart extends BaseClientSideWebPart<IListItemsFormWebPartProps> {  
  27.   private listName: string = "";  
  28.   private checkboxProperty1: string = "Created";  
  29.   private checkboxProperty2: string = "Author";  
  30.   
  31.   public constructor(context: IWebPartContext) {  
  32.     super(context);  
  33.   }  
  34.   
  35.   public render(): void {  
  36.     // Render the items in tabular format  
  37.     this.domElement.innerHTML = `  
  38.       <div class="${styles.listItemsForm}">  
  39.         <div class="${styles.Table}">  
  40.           <div class="${styles.Heading}">  
  41.             <div class="${styles.Cell}">Title</div>  
  42.           </div>  
  43.         </div>  
  44.       </div>`;  
  45.   
  46.       this.listName = "TestList";  
  47.       this.LoadData();  
  48.   }  
  49.   
  50.   private LoadData(): void{  
  51.   
  52.     let url: string = this.context.pageContext.web.absoluteUrl + "/_api/web/lists/getbytitle('"+this.listName+"')/items?$select=Title";  
  53.     // If Created Time check box option is selected  
  54.     if(this.properties.checkboxProperty1){  
  55.       url += ",Created";  
  56.       // Column header for Created Time field  
  57.        this.domElement.querySelector("."+styles.Heading).innerHTML +=`<div class="${styles.Cell}">Created</div>`;  
  58.     }  
  59.     // If Author check box option is selected  
  60.     if(this.properties.checkboxProperty2){  
  61.       url += ",Author/Title&$expand=Author";  
  62.       // Column header for Author field  
  63.       this.domElement.querySelector("."+styles.Heading).innerHTML +=`<div class="${styles.Cell}">Author</div>`;  
  64.     }  
  65.   
  66.     this.GetListData(url).then((response)=>{  
  67.       // Render the data in the web part  
  68.       this.RenderListData(response.value);  
  69.     });  
  70.   }  
  71.   
  72.   private GetListData(url: string): Promise<spListItems>{  
  73.     // Retrieves data from SP list  
  74.     return this.context.httpClient.get(url).then((response: Response)=>{  
  75.        return response.json();  
  76.     });  
  77.   }  
  78.   private RenderListData(listItems: spListItem[]): void{  
  79.     let itemsHtml: string = "";  
  80.     // Displays the values in table rows  
  81.     listItems.forEach((listItem: spListItem)=>{  
  82.       let itemTimeStr: string = listItem.Created;  
  83.       let itemTime: Date = new Date(itemTimeStr);  
  84.       itemsHtml += `<div class="${styles.Row}">`;  
  85.       itemsHtml += `<div class="${styles.Cell}"><p>${listItem.Title}</p></div>`;  
  86.       if(this.properties.checkboxProperty1){  
  87.         itemsHtml += `<div class="${styles.Cell}"><p>${listItem.Created}</p></div>`;  
  88.       }  
  89.       if(this.properties.checkboxProperty2){  
  90.         itemsHtml += `<div class="${styles.Cell}"><p>${listItem.Author.Title}</p></div>`;  
  91.       }  
  92.   
  93.       itemsHtml += `</div>`;  
  94.     });  
  95.     this.domElement.querySelector("."+styles.Table).innerHTML +=itemsHtml;  
  96.   }  
  97.   protected get propertyPaneSettings(): IPropertyPaneSettings {  
  98.     return {  
  99.       pages: [  
  100.         {  
  101.           header: {  
  102.             description: strings.PropertyPaneDescription  
  103.           },  
  104.           groups: [  
  105.             {  
  106.               groupName: strings.BasicGroupName,  
  107.               groupFields: [  
  108.                 PropertyPaneTextField('description', {  
  109.                   label: strings.DescriptionFieldLabel  
  110.                 })  
  111.               ]  
  112.             },  
  113.             {  
  114.               groupName: "OptionalFields",  
  115.               groupFields: [  
  116.                 PropertyPaneCheckbox('checkboxProperty1',{  
  117.                   isChecked:false,  
  118.                   isEnabled:true,  
  119.                   text: this.checkboxProperty1  
  120.                 }),  
  121.                 PropertyPaneCheckbox('checkboxProperty2',{  
  122.                   isChecked:false,  
  123.                   isEnabled:true,  
  124.                   text: this.checkboxProperty2  
  125.                 })  
  126.               ]  
  127.             }  
  128.           ]  
  129.         }  
  130.       ]  
  131.     };  
  132.   }  
  133. }   
Summary

Thus, you have learned how to add the check box fields to the SharePoint Framework web part properties.
 
What Next
 
In the next articles, you will learn about working with multiple pages on the property pane and adding other custom properties that are available.