The SharePoint Framework contains a set of standard controls for the property pane. But sometimes you need additional functionality beyond the basic controls. You might need asynchronous updates to the data on a control or a specific user interface. Build a custom control for the property pane to get the functionality you need.
In this post I show how to build a text box property pane using Typescript, i.e easy way to create simple custom Property Pane without react.
Note : Next post I will show you how to build a custom property pane using React.js

Steps
Step 1:
Open command Prompt and create a folder “spfxCustomPropertyPane” under your favourite SPFx project

Step 2:
Create a new ” PropertyPaneCustomTextField ” web part by running the Yeoman SharePoint Generator.
When prompted fill all solution and web part information, refer below


Because the SharePoint client-side solution is HTML/TypeScript based, you can use any code editor that supports client-side development to build your web part. Here I am using Visual Studio Code
Step 3
Open the code in Visual Studio Code – for that type code . in the command Prompt
Create a folder “Modules” under web part folder, refer below
Create a file ” PropertyPaneCustomTextField.ts” under Modules folder, manage the control functionality.

Open the PropertyPaneCustomTextField.ts file
Import the Custom Property Pane Class and Interfaces
IPropertyPaneCustomFieldProps – This interface provides key properties and methods that help in developing the pane property. Properties and methods available are the following.
IPropertyPaneField – This interface provides a few properties that can be inherited for defining the custom pane property
import { IPropertyPaneField, IPropertyPaneCustomFieldProps, PropertyPaneFieldType } from '@microsoft/sp-property-pane';
Create interface “PropertyPaneCustomTextFieldProps” to structure your Property Pane parameters. The property definition is written as a function which inherits data from class and interface components. Here, a custom interface is introduced to input the user defined custom properties.
export interface IPropertyPaneCustomTextFieldProps{
properties:any;
label:string;
description?:string;
color?:string;
backgroundcolor?:string;
defaultvalue?:string;
}
In this above interface i have added properties to get all control properties
- label to give a header to the control
- ? means optional property
- description to give control details below the control
- color to give label font color
- backgroundcolor to give control background
- defaultvalue to give default value to the control
Create a class “PropertyPaneCustomTextField“ and implements IPropertyPaneField and type IPropertyPaneCustomFieldProps, the class is defined, which contains the variables, constructor, and render method
export class PropertyPaneCustomTextField implements IPropertyPaneField<IPropertyPaneCustomFieldProps>
{
}
Declare IPropertyPaneCustomFieldProps mandatory variables
public type: any = PropertyPaneFieldType.Custom;
public targetProperty:string;
public properties: IPropertyPaneCustomFieldProps;
Declare two local variable to get all properties as config and maintain the currentvaue
private config : IPropertyPaneCustomTextFieldProps;
private currentValue:string = "";
Then create a constructor to get all property inputs from user, In this constructor get all config property parameters, webpart context, and initial render and dispose events. Also create two methods to handle render and dispose events and assign the config parameter to local config variable.
The constructor is used to initialise the variables.
constructor(targetProperty:string,
config : IPropertyPaneCustomTextFieldProps,
context?:any)
{
this.targetProperty = targetProperty;
this.properties = {
key: "MyCustomControl",
context: context,
onRender : this.render.bind(this),
onDispose : this.dispose.bind(this)
};
this.config = config;
}
private render()
{
}
private dispose()
{
}
The render method will display the data. The custom function or the components are used for rendering the data.
Inside the render method to build the control and add events, here I have added HeaderLabel, Textbox and description label with configure default textbox value, description, background color and label header font color
${this.config.backgroundcolor}
${this.config.color}
${this.config.defaultvalue}
${this.config.description
private render(element:HTMLElement, context:any,changeCallback:(targetProperty:string, newValue:any)=>void)
{
this.currentValue = this.config.properties[this.targetProperty];
let html =
`<div style="border: 1px solid #ccc!important;border-radius: 5px;padding-left: 5px;padding-right: 3px;background-color:${this.config.backgroundcolor || "red"}">
<div class="ms-TexField">
<div class="ms-TextFied-wrapper">
<label style="display: block;width: 100%;color:${this.config.color || "yellow"};">${this.config.label}</label>
<input style="padding: 8px;display: block;width: 93%;border: 1px solid #ccc!important;border-radius: 5px" type="text" value="${this.currentValue || this.config.defaultvalue || ""}">
</div>
</div>
<span class="description">${this.config.description || ""}</span>
</div>
</div>
`;
element.innerHTML = html;
this.addEvents(element,changeCallback);
}
Add two local method to manage events, add the events to your control, then add the functionality for the events. Here I am get the value from textbox using on change and assign to current value i,e newValue.
private addEvents(element:HTMLElement, callback:(targetProperty:string, newValue:any)=>void ){
let inputTextElement : HTMLInputElement = element.getElementsByTagName('input')[0];
inputTextElement.onchange=()=>{
this.applyChanges(element, inputTextElement, callback);
};
}
private applyChanges(element: HTMLElement, inputTextElement : HTMLInputElement, callback:(targetProperty:string, newValue:any)=>void ){
let newValue = inputTextElement.value;
callback(this.targetProperty, newValue);
}
Finally add dispose method to clear the htmlelement
private dispose(element:HTMLElement)
{
element.innerHTML = "";
}
Now our Property control is ready, need to use the custom property pane module in our webpart. for that Import the module in webpart
import { PropertyPaneCustomTextField } from "./../Modules/PropertyPaneCustomTextField";
The goto getPropertyPaneConfiguration() method and add new custom propertypane
new PropertyPaneCustomTextField('mytextbox',{
properties: this.properties,
label:"Full Name",
description:"Please enter full name",
color:"green",
backgroundcolor:"yellow",
defaultvalue: "default value"
})
To bring the return value to webpart
Add the propertypane control name in props, then get the propoerties value from renderwebpart method
export interface IPropertyPaneCustomTextFieldWebPartProps {
description: string;
mytextbox:string;
}
<p class="${ styles.description }">${escape(this.properties.mytextbox)}</p>
gulp serve and execute the webpart
After adding the web part to the page for the first time and opening its property pane and see the custom propertypane


Conclusion
SharePoint Framework contains a set of standard controls for the property pane. But sometimes you need additional functionality beyond the basic controls. SharePoint Framework allows you to build custom controls to deliver the required functionality. In this post you learned how to create a simple custom property pane using Typescript.
Here you have learned how to build simple custom pane property which can be added to property panes. The interfaces, class, and functions are used for defining the data. The rendering can be done on the same file or using components.
In the next article, how to build the custom pane property pane using react components.