Property Pane in SPFx: Developer Guide
When building a SharePoint Framework (SPFx) web part, one of the most important concepts to master is the Property Pane.
The Property Pane is the configuration panel that allows users to customize a web part without changing code.
It is the bridge between:
- Developer-defined configuration
- User customization
- Runtime rendering
Without it, every SPFx web part would be static.
What is Property Pane?
In SPFx, every web part inherits from:
BaseClientSideWebPart<TProperties>
The generic type (TProperties) defines the configurable properties.
Example:
export interface IMyWebPartProps { title: string; description: string;}
These properties are stored by SharePoint in the page JSON.
That means:
- each instance of the web part can have different values
- values persist after publishing
- values can be exported/imported with page templates
Flow:
Property Pane → User changes values → SPFx stores values → Render() updates UI
The Architecture
SPFx Property Pane has 4 major parts:
1. Properties Interface
Defines what can be configured.
export interface IHelloWorldWebPartProps { title: string; itemsPerPage: number; showImages: boolean;}
2. Web Part Class
The values are available through:
this.properties
Example:
public render(): void { const element = React.createElement( HelloWorld, { title: this.properties.title, itemsPerPage: this.properties.itemsPerPage } );}
3. Property Pane Configuration
Implemented inside:
protected getPropertyPaneConfiguration(): IPropertyPaneConfiguration
This defines the UI.
Example:
protected getPropertyPaneConfiguration(): IPropertyPaneConfiguration { return { pages: [ { header: { description: "Web Part Settings" }, groups: [ { groupName: "General Settings", groupFields: [ PropertyPaneTextField('title', { label: 'Title' }) ] } ] } ] };}
4. Reactive Engine
SPFx automatically updates:
this.properties
and rerenders.
Default SPFx Property Controls
SPFx ships with several controls.
PropertyPaneTextField
Most used.
Example:
PropertyPaneTextField('title', { label: 'Web Part Title'})
Use cases:
- Titles
- URLs
- Search terms
- IDs
PropertyPaneDropdown
For fixed options.
Example:
PropertyPaneDropdown('layout', { label: 'Layout', options: [ { key: 'grid', text: 'Grid' }, { key: 'list', text: 'List' } ]})
Best for:
- Layout selection
- Status
- Categories
PropertyPaneToggle
Boolean values.
Example:
PropertyPaneToggle('showImages', { label: 'Show Images', onText: 'Yes', offText: 'No'})
Returns:
true | false
PropertyPaneSlider
Numeric ranges.
Example:
PropertyPaneSlider('itemsPerPage', { label: 'Items', min: 1, max: 20, step: 1})
Perfect for:
- pagination
- animation speed
- card sizes
PropertyPaneCheckbox
Simple boolean.
PropertyPaneCheckbox('enableLogging', { text: 'Enable Logging'})
PropertyPaneChoiceGroup
Radio buttons.
PropertyPaneChoiceGroup('theme', { label: 'Theme', options: [ { key: 'light', text: 'Light' }, { key: 'dark', text: 'Dark' } ]})
PropertyPaneButton
Executes actions.
Example:
PropertyPaneButton('refresh', { text: 'Refresh Data', buttonType: PropertyPaneButtonType.Primary})
Useful for:
- clearing cache
- reloading data
PropertyPaneLabel
Read-only text.
Example:
PropertyPaneLabel('', { text: 'Version 1.0'})
Full Real Example
WebPart.ts
import * as React from 'react';import * as ReactDom from 'react-dom';import { BaseClientSideWebPart} from '@microsoft/sp-webpart-base';import { IPropertyPaneConfiguration, PropertyPaneTextField, PropertyPaneDropdown, PropertyPaneToggle, PropertyPaneSlider} from '@microsoft/sp-property-pane';import DemoComponent from './components/DemoComponent';export interface IDemoWebPartProps { title: string; layout: string; showImages: boolean; itemsPerPage: number;}export default class DemoWebPart extends BaseClientSideWebPart<IDemoWebPartProps> { public render(): void { const element = React.createElement(DemoComponent, { title: this.properties.title, layout: this.properties.layout, showImages: this.properties.showImages, itemsPerPage: this.properties.itemsPerPage }); ReactDom.render(element, this.domElement); } protected getPropertyPaneConfiguration(): IPropertyPaneConfiguration { return { pages: [ { header: { description: "Demo Settings" }, groups: [ { groupName: "Main Settings", groupFields: [ PropertyPaneTextField('title', { label: 'Title' }), PropertyPaneDropdown('layout', { label: 'Layout', options: [ { key: 'grid', text: 'Grid' }, { key: 'list', text: 'List' } ] }), PropertyPaneToggle('showImages', { label: 'Show Images' }), PropertyPaneSlider('itemsPerPage', { label: 'Items Per Page', min: 1, max: 20 }) ] } ] } ] }; }}
Reactive vs Non-Reactive
SPFx supports two modes.
Reactive
Default.
Every change rerenders immediately.
protected get disableReactivePropertyChanges(): boolean { return false;}
Behavior:
type → rerendertoggle → rerenderslider → rerender
Best UX.
Non-Reactive
Requires Apply button.
protected get disableReactivePropertyChanges(): boolean { return true;}
Best for:
- API calls
- expensive rendering
- large datasets
Example:
Imagine a search web part.
Reactive:
Typing "SharePoint"S → API callSh → API callSha → API call
Bad.
Non-reactive:
Type everything → click Apply → 1 API call
Better.
Dynamic Property Pane
Fields can appear conditionally.
Example:
if (this.properties.layout === 'grid') { fields.push( PropertyPaneSlider('columns', { label: 'Columns', min: 1, max: 6 }) );}
This makes Property Pane intelligent.
Async Loading Data
Example: loading SharePoint lists.
protected async onPropertyPaneConfigurationStart(): Promise<void> { this.lists = await this.loadLists(); this.context.propertyPane.refresh();}
Critical for:
- ListPicker
- SitePicker
- TaxonomyPicker
Validation
SPFx allows validation.
Example:
PropertyPaneTextField('url', { label: 'Site URL', onGetErrorMessage: (value) => { if (!value.startsWith('https://')) { return 'URL must start with https://'; } return ''; }})
This prevents bad input.
Performance Considerations
Property Pane can affect performance.
Avoid:
❌ API calls inside render
Bad:
render() { this.loadData();}
Good:
protected async onPropertyPaneFieldChanged(): Promise<void> { await this.loadData();}
Advanced Lifecycle Methods
onPropertyPaneFieldChanged
Triggered when a field changes.
protected onPropertyPaneFieldChanged( propertyPath: string, oldValue: any, newValue: any): void { if (propertyPath === 'title') { console.log('Title changed'); }}
onDispose
Cleanup.
protected onDispose(): void { ReactDom.unmountComponentAtNode(this.domElement);}
PnP Property Controls
SPFx default controls are limited.
The PnP SPFx React Controls library extends Property Pane heavily.
Examples:
- PropertyFieldCollectionData
- PropertyFieldColorPicker
- PropertyFieldFilePicker
- PropertyFieldFolderPicker
- PropertyFieldPeoplePicker
- PropertyFieldTermPicker
- PropertyFieldSitePicker
These are essential for enterprise SPFx.
Your roadmap already includes 26 Property Pane controls .
Best Practices
Keep configuration simple
Good:
TitleLayoutMax ItemsShow Images
Bad:
35 confusing options
Group logically
Good:
GeneralDataDisplayAdvanced
Validate everything
Never trust user input.
Use non-reactive for API-heavy components
Important for performance.
Hide advanced settings
Use dynamic fields.
Why Property Pane is so important
Property Pane transforms:
Static web parts → configurable applications
Without it:
One hardcoded behavior
With it:
Infinite reusable configurations
This is why mastering Property Pane is fundamental for serious SPFx development.
It is not just configuration.
It is the developer-user contract.
