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 → rerender
toggle → rerender
slider → 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 call
Sh → API call
Sha → 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:

Title
Layout
Max Items
Show Images

Bad:

35 confusing options

Group logically

Good:

General
Data
Display
Advanced

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.

Edvaldo Guimrães Filho Avatar

Published by