How to add custom controls in SPFx property pane

This SPFx tutorial will see to add custom controls in SPFx property pane in the SharePoint framework. By the end of the tutorial, you can also download the SPFx solution and run it.

The SharePoint Framework includes a collection of basic property pane controls. However, there are situations when you want more capability in addition to the basic controls. Asynchronous changes to data on control or a specialized user interface may be required. To acquire the functionality you want, create a custom control for the property pane.

Here we will discuss the following topics:

  • What is the property pane in SharePoint Framework?
  • What is the use of the property pane in spfx?
  • Add custom controls in SPFx property pane
    • Create a web part property to store the selected list
    • How to define dropdown control in the Property pane in spfx
    • Add a property pane dropdown control React component
    • Add dropdown control to the property pane
    • Use the dropdown property pane control inside the web part

What is a property pane in spfx?

The property pane enables end users to customize the SPFx web part with various attributes. Property pane settings specify the properties of the Property pane.

What is the use of the property pane in spfx?

In SharePoint Framework, a property pane has three types of metadata: a page, an optional header, and at least one group.

  • Pages allow you to split complicated interactions into one or more pages. Pages have a header as well as groups.
  • Headers enable you to customize the title of the property window.
  • Groups enable you to create the various sections or fields for the property pane via which you wish to group your fieldsets.

Read SharePoint Framework (SPFx) Extensions Application Customizer Example

Add custom controls in the SPFx property pane

Here we will add custom controls in the SharePoint Framework property pane, to acquire functionality like asynchronous updates to the data on the control or a specific UI.

Now we will see how to create a custom dropdown control that loads its data asynchronously from an external service without interfering with the web part’s user experience.

In the First step, we create a web part property to store the selected list. And then we will define a custom dropdown control for that selected list, web part property.

Note:

To follow the steps to build custom dropdown control for the selected list, make sure you have setup the development environment as well as you have create the Spfx solution by running the command ‘yo @microsoft/sharepoint‘ in the solution directory.
While running the command the Yeoman will ask you list of questions, so on that select the Framework to use as React.

Create a web part property to store the selected list in the SharePoint framework

We will create an SPFx web part property that will display the list items from the selected SharePoint list. So that user can choose a list item from the list web part properties. To hold the selected list, define a new web part property named ‘departmentName’.

How to add custom controls in SPFx property pane
How to add custom controls in SPFx property pane

In the Code Editor, open the ListItemsWebPart.manifest.json file which is available in ‘ src\webparts\listItems\ListItemsWebPart.manifest.json’. So in this file, we will replace the default description property with a new property ‘departmentName‘, and set it as an empty string.

{
  "$schema": "https://developer.microsoft.com/json-schemas/spfx/client-side-web-part-manifest.schema.json",
  "id": "d099883a-c489-4cc7-99d4-206c56ebf5d8",
  "alias": "ListItemsWebPart",
  "componentType": "WebPart",

  
  "version": "*",
  "manifestVersion": 2,

  
  "requiresCustomScript": false,
  "supportedHosts": ["SharePointWebPart", "TeamsPersonalApp", "TeamsTab", "SharePointFullPage"],
  "supportsThemeVariants": true,

  "preconfiguredEntries": [{
    "groupId": "5c03119e-3074-46fd-976b-c60198311f70", 
    "group": { "default": "Advanced" },
    "title": { "default": "List items" },
    "description": { "default": "List items description" },
    "officeFabricIconFontName": "Page",
    "properties": {
      "departmentName": ""
    }
  }]
}

Next update the interface IListItemsWebPartProps in the ‘src\webparts\listItems\ListItemsWebPart.ts‘ file with the below code.

export interface IListItemsWebPartProps {
  description: string;
  departmentName: string;
}

On the same ListItemsWebPart.ts file update the render method with the below code:

public render(): void {
    const element: React.ReactElement<IListItemsProps> = React.createElement(
      ListItems,
      {
        departmentName: this.properties.departmentName,
        description: this.properties.description,
        isDarkTheme: this._isDarkTheme,
        environmentMessage: this._environmentMessage,
        hasTeamsContext: !!this.context.sdks.microsoftTeams,
        userDisplayName: this.context.pageContext.user.displayName
      }
    );

    ReactDom.render(element, this.domElement);
  }

Also in the same ‘ListItemsWebPart.ts file updates the code in the getPropertyPaneConfiguration():

protected getPropertyPaneConfiguration(): IPropertyPaneConfiguration {
    return {
      pages: [
        {
          header: {
            description: strings.PropertyPaneDescription
          },
          groups: [
            {
              groupName: strings.BasicGroupName,
              groupFields: [
                PropertyPaneTextField('departmentName', {
                  label: strings.ListFieldLabel
                })
              ]
            }
          ]
        }
      ]
    };
  }

Open the mystrings.d.ts file available in the ‘src\webparts\listItems\loc\mystrings.d.ts‘, so in the existing IListItemsWebPartStrings interface, add a new property named as ‘ListFieldLabel’ as type string.

declare interface IListItemsWebPartStrings {
  PropertyPaneDescription: string;
  BasicGroupName: string;
  DescriptionFieldLabel: string;
  AppLocalEnvironmentSharePoint: string;
  AppLocalEnvironmentTeams: string;
  AppSharePointEnvironment: string;
  AppTeamsTabEnvironment: string;
  ListFieldLabel: string;
}

declare module 'ListItemsWebPartStrings' {
  const strings: IListItemsWebPartStrings;
  export = strings;
}

Open the en-us.js file available in ‘src\webparts\listItems\loc\en-us.js‘, in this add a new property ‘ListFieldLabel’ to the returned object which is ‘List’.

define([], function() {
  return {
    "PropertyPaneDescription": "Description",
    "BasicGroupName": "Group Name",
    "DescriptionFieldLabel": "Description Field",
    "AppLocalEnvironmentSharePoint": "The app is running on your local environment as SharePoint web part",
    "AppLocalEnvironmentTeams": "The app is running on your local environment as Microsoft Teams app",
    "AppSharePointEnvironment": "The app is running on SharePoint page",
    "AppTeamsTabEnvironment": "The app is running in Microsoft Teams",
    "ListFieldLabel": "Department"
  }
});

Open the IListItemsProps.ts file available in ‘src\webparts\listItems\components\IListItemsProps.ts‘ file, add the departmentName property to the ‘interface IListItemsProps’.

export interface IListItemsProps {
  description: string;
  isDarkTheme: boolean;
  environmentMessage: string;
  hasTeamsContext: boolean;
  userDisplayName: string;
  departmentName: string;
}

At last, open the ‘ListItems.tsx’ file available in the ‘src\webparts\listItems\components\ListItems.tsx’, update the render method to:

import * as React from 'react';
import styles from './ListItems.module.scss';
import { IListItemsProps } from './IListItemsProps';
import { escape } from '@microsoft/sp-lodash-subset';

export default class ListItems extends React.Component<IListItemsProps, {}> {
  public render(): React.ReactElement<IListItemsProps> {
    const {
      description,
      isDarkTheme,
      environmentMessage,
      hasTeamsContext,
      userDisplayName,
      departmentName
    } = this.props;

    return (
      <section className={`${styles.listItems} ${hasTeamsContext ? styles.teams : ''}`}>
        <div className={styles.welcome}>
          <img alt="" src={isDarkTheme ? require('../assets/welcome-dark.png') : require('../assets/welcome-light.png')} className={styles.welcomeImage} />
          <h2>Well done, {escape(userDisplayName)}!</h2>
          <div>{environmentMessage}</div>
          <div>Department name: <strong>{escape(departmentName)}</strong></div>
        </div>
      </section>
    );
  }
}

Now to test the code that is running, use the below command to run the program in the local host.

gulp serve
Create a web part property to store the selected list
Create a web part property to store the selected list

Read Create and Deploy SharePoint Framework (SPFx) extension field customizer

See also  Display SharePoint list items using SPFx (SharePoint Framework) + 2 Ways

How to define dropdown control in Property pane in spfx

The SharePoint Framework includes a typical dropdown control that lets users choose a value. The dropdown control is designed in such a way that all of its settings must be known in advance.

If you want to load the values dynamically or asynchronously from an external service with spfx and don’t want to block the entire spfx web part, using a custom dropdown control is an alternative.

In the SharePoint Framework, a custom property pane control that uses React consists of a class that registers the control with the web part and a React component that renders the dropdown and handles its data.

Add a property pane dropdown control React component in SPfx

Here we will see how to add a dropdown control property pane with react component in SharePoint framework.

First, we will create a components folder, so create a new folders hierarchy inside the src folder-> controls -> AsyncDropdownPropertyPane -> Components.

Then inside the Components folder create a new file, named as ‘IAsyncDropdownProps.ts‘ file. In this file write the below code.

import { IDropdownOption } from 'office-ui-fabric-react/lib/components/Dropdown';

export interface IDropdownPropsAsync {
  label: string;
  loadOptions: () => Promise<IDropdownOption[]>;
  onChanged: (option: IDropdownOption, index?: number) => void;
  selectedKey: string | number;
  disabled: boolean;
  stateKey: string;
}

The IAsyncDropdownProps class defines attributes that may be set on the React component used by the custom property pane control.

  1. The label attribute defines the dropdown control’s label.
  2. The control calls the function associated with the loadOptions delegate to load the available options.
  3. After the user picks an option from the dropdown, the function associated with the onChanged delegate is invoked.
  4. The selectedKey property indicates the value that was chosen, which can be either a string or an integer.
  5. The disabled property determines whether or not the dropdown control is disabled.
  6. The stateKey property is used to compel the React component to re-render.

Now we will define the interface for an asynchronous dropdown React component. Create a new file entitled IAsyncDropdownState.ts in the src/controls/PropertyPaneAsyncDropdown/components folder, and insert the following code:

import { IDropdownOption } from 'office-ui-fabric-react/lib/components/Dropdown';

export interface IDropdownStateAsync {
  loading: boolean;
  options: IDropdownOption[];
  error: string;
}

The IAsyncDropdownState interface describes the React component’s state:

  1. The loading property specifies whether or not the component is loading its options at the time specified.
  2. All possible options are shown in the options property.
  3. If an error occurs, it is assigned to the error property and conveyed to the user.

Define the React component asynchronous dropdown. Create a new file titled AsyncDropdown.tsx in the src/controls/PropertyPaneAsyncDropdown/components folder, and insert the following code:

import * as React from 'react';
import { Dropdown, IDropdownOption } from 'office-ui-fabric-react/lib/components/Dropdown';
import { Spinner } from 'office-ui-fabric-react/lib/components/Spinner';
import { IDropdownPropsAsync } from './IAsyncDropdownProps';
import { IDropdownStateAsync } from './IAsyncDropdownState';

export default class AsyncDropdown extends React.Component<IDropdownPropsAsync, IDropdownStateAsync> {
  private selectedKey: React.ReactText;

  constructor(props: IDropdownPropsAsync, state: IDropdownStateAsync) {
    super(props);
    this.selectedKey = props.selectedKey;

    this.state = {
      loading: false,
      options: undefined,
      error: undefined
    };
  }

  public componentDidMount(): void {
    this.loadOptions();
  }

  public componentDidUpdate(prevProps: IDropdownPropsAsync, prevState: IDropdownStateAsync): void {
    if (this.props.disabled !== prevProps.disabled ||
      this.props.stateKey !== prevProps.stateKey) {
      this.loadOptions();
    }
  }

  private loadOptions(): void {
    this.setState({
      loading: true,
      error: undefined,
      options: undefined
    });

    this.props.loadOptions()
      .then((options: IDropdownOption[]): void => {
        this.setState({
          loading: false,
          error: undefined,
          options: options
        });
      }, (error: any): void => {
        this.setState((prevState: IDropdownStateAsync, props: IDropdownPropsAsync): IDropdownStateAsync => {
          prevState.loading = false;
          prevState.error = error;
          return prevState;
        });
      });
  }

  public render(): JSX.Element {
    const loading: JSX.Element = this.state.loading ? <div><Spinner label={'Loading options...'} /></div> : <div />;
    const error: JSX.Element = this.state.error !== undefined ? <div className={'ms-TextField-errorMessage ms-u-slideDownIn20'}>Error while loading items: {this.state.error}</div> : <div />;

    return (
      <div>
        <Dropdown label={this.props.label}
          disabled={this.props.disabled || this.state.loading || this.state.error !== undefined}
          onChanged={this.onChanged.bind(this)}
          selectedKey={this.selectedKey}
          options={this.state.options} />
        {loading}
        {error}
      </div>
    );
  }

  private onChanged(option: IDropdownOption, index?: number): void {
    this.selectedKey = option.key;
    // reset previously selected options
    const options: IDropdownOption[] = this.state.options;
    options.forEach((o: IDropdownOption): void => {
      if (o.key !== option.key) {
        o.selected = false;
      }
    });
    this.setState((prevState: IDropdownStateAsync, props: IDropdownPropsAsync): IDropdownStateAsync => {
      prevState.options = options;
      return prevState;
    });
    if (this.props.onChanged) {
      this.props.onChanged(option, index);
    }
  }
}

The React component used to render the asynchronous dropdown property pane control is represented by the AsyncDropdown class:

  • The componentDidMount() function, or its disabled or stateKey properties, change when it initially loads, and it loads the available choices by calling the loadOptions() method supplied through the properties.
  • The component’s state in spfx is updated to indicate the available options when the options are loaded.
  • The Office UI Fabric React dropdown component is used to render the dropdown.
  • The Office UI Fabric React spinner component is used to display a spinner when the component is loading the available choices.
See also  (SPFx) SharePoint framework client web part example

The following step is to create the custom property pane control. When specifying properties in the property pane, this control is utilized inside the web section and renders using the previously specified React component.

Read Create and deploy SharePoint Framework (SPFx) listview command set extension

Add dropdown control to the SharePoint Framework property pane

Here we will see how to add a property pane asynchronous dropdown control.

We will define the properties for the asynchronous dropdown property pane control. Two sets of properties are available in a custom property pane control.

The first set of properties is visible to the public and is used to specify the web part property within the web component. These are component-specific attributes, such as the label shown adjacent to the control, the minimum and maximum values for a spinner, or the dropdown’s available selections.

When implementing the IPropertyPaneFieldTProperties> interface, the type specifying these properties must be supplied as the TProperties type when constructing a custom property pane control.

The second set of properties is a collection of private properties that are utilized internally by the custom property pane control in spfx. For the custom control in spfx to render effectively, these properties must conform to the SharePoint Framework APIs. The IPropertyPaneCustomFieldProps interface from the @microsoft/sp-property-pane package must be implemented by these properties.

  1. Firstly, define the asynchronous dropdown property pane control’s public properties. Create a new file titled IAsyncPropertyPaneDropdownProps .ts in the src/controls/PropertyPaneAsyncDropdown folder, and insert the following code:
import { IDropdownOption } from 'office-ui-fabric-react/lib/components/Dropdown';

export interface IAsyncPropertyPaneDropdownProps {
  label: string;
  loadOptions: () => Promise<IDropdownOption[]>;
  onPropertyChange: (propertyPath: string, newValue: any) => void;
  selectedKey: string | number;
  disabled?: boolean;
}

In the interface IPropertyPaneAsyncDropdownProps:

  • label: specifies the label that appears next to the dropdown.
  • loadOptions: specifies the method used to load the available dropdown choices.
  • onPropertyChange: provides a method that is invoked when a value from the dropdown is selected.
  • selectedKey: The selected dropdown value is returned by selectedKey.
  • disabled: defines whether or not the control is disabled.

2. Define the asynchronous dropdown property pane control’s internal properties. Create a new file titled IPropertyPaneAsyncDropdownInternalProps .ts in the src/controls/PropertyPaneAsyncDropdown folder, and insert the following code:

import { IPropertyPaneCustomFieldProps } from '@microsoft/sp-property-pane';
import { IAsyncPropertyPaneDropdownProps } from './IAsyncPropertyPaneDropdownProps';

export interface IPropertyPaneDropdownInternalProps extends IAsyncPropertyPaneDropdownProps, IPropertyPaneCustomFieldProps {
}

While the IPropertyPaneAsyncDropdownInternalProps interface does not define any new properties, it combines the properties from the previously defined IPropertyPaneAsyncDropdownProps interface and the standard SharePoint Framework IPropertyPaneCustomFieldProps interface, both of which are required for a custom control to function properly.

Define the asynchronous dropdown property pane control. Create a new file titled PropertyPaneAsyncDropdown.ts in the src/controls/PropertyPaneAsyncDropdown folder, and insert the following code:

PropertyPaneAsyncDropdown.ts

import * as React from 'react';
import * as ReactDom from 'react-dom';
import {
  IPropertyPaneField,
  PropertyPaneFieldType
} from '@microsoft/sp-property-pane';
import { IDropdownOption } from 'office-ui-fabric-react/lib/components/Dropdown';
import { IPropertyPaneDropdownInternalProps } from './IPropertyPaneDropdownInternalProps';
import { IAsyncPropertyPaneDropdownProps } from './IAsyncPropertyPaneDropdownProps';
import AsyncDropdown from '../Components/AsyncDropdown';
import { IDropdownPropsAsync } from '../Components/IAsyncDropdownProps';

export class PropertyPaneAsyncDropdown implements IPropertyPaneField<IAsyncPropertyPaneDropdownProps> {
  public type: PropertyPaneFieldType = PropertyPaneFieldType.Custom;
  public targetProperty: string;
  public properties: IPropertyPaneDropdownInternalProps;
  private elem: HTMLElement;

  constructor(targetProperty: string, properties: IAsyncPropertyPaneDropdownProps) {
    this.targetProperty = targetProperty;
    this.properties = {
      key: properties.label,
      label: properties.label,
      loadOptions: properties.loadOptions,
      onPropertyChange: properties.onPropertyChange,
      selectedKey: properties.selectedKey,
      disabled: properties.disabled,
      onRender: this.onRender.bind(this),
      onDispose: this.onDispose.bind(this)
    };
  }

  public render(): void {
    if (!this.elem) {
      return;
    }

    this.onRender(this.elem);
  }

  private onDispose(element: HTMLElement): void {
    ReactDom.unmountComponentAtNode(element);
  }

  private onRender(elem: HTMLElement): void {
    if (!this.elem) {
      this.elem = elem;
    }

    const element: React.ReactElement<IDropdownPropsAsync> = React.createElement(AsyncDropdown, {
      label: this.properties.label,
      loadOptions: this.properties.loadOptions,
      onChanged: this.onChanged.bind(this),
      selectedKey: this.properties.selectedKey,
      disabled: this.properties.disabled,
      // required to allow the component to be re-rendered by calling this.render() externally
      stateKey: new Date().toString()
    });
    ReactDom.render(element, elem);
  }

  private onChanged(option: IDropdownOption, index?: number): void {
    this.properties.onPropertyChange(this.targetProperty, option.key);
  }
}

Read Delete node_modules from SPFx solution

Use dropdown property pane control inside an SPFx web part

The asynchronous dropdown property pane control is now ready to be used inside the web component to allow users to pick from a list. So follow the below path to achieve this.

See also  Set up SharePoint Framework (SPFx) development environment

Include a list info interface
Define an interface that represents list information to send information about accessible lists around in a consistent manner. Create a new file titled IListInfo.ts in the src/webparts/listItems folder and insert the following code:

export interface IInfoLists {
    Id: string;
    Title: string;
  }

To display the departmentName web part property, use the dropdown property pane control

Now we will see how to display the department name web part property, with the dropdown property pane control.

  • To reference the required types, import the previously generated PropertyPaneAsyncDropdown class at the start of the src/webparts/listItems/ListItemsWebPart.ts file by adding the below code:
import { PropertyPaneDropdown } from '../../controls/AsyncDropdownPropertyPane/PropertyPaneAsyncDropdown/PropertyPaneDropdown';
  • After that, provide a reference to the IDropdownOption interface as well as two utility methods for working with web part properties.
import { IDropdownOption } from 'office-ui-fabric-react/lib/components/Dropdown';
import { update, get } from '@microsoft/sp-lodash-subset';
  • To load available lists in spfx webpart, add the loadLists() function to the ListItemsWebPart class. You utilize mock data over here, but you could alternatively use the SharePoint REST API to get a list of accessible lists from the current site. The solution employs a 3 seconds delay to simulate loading choices from an external service.
private loadLists(): Promise<IDropdownOption[]> {
    return new Promise<IDropdownOption[]>((resolve: (options: IDropdownOption[]) => void, reject: (error: any) => void) => {
      setTimeout(() => {
        resolve([{
          key: 'finance',
          text: 'Finance'
        },
          {
            key: 'development',
            text: 'Development'
          }]);
      }, 2000);
    });
  }
  • Now we will add a function to manage the value in the dropdown changing. So for this add a new method named onChangeList to the ListItemsWebPart class ().
 private onChangeList(propertyPath: string, newValue: any): void {
    const oldValue: any = get(this.properties, propertyPath);
    // store new value in web part properties
    update(this.properties, propertyPath, (): any => { return newValue; });
    // refresh web part
    this.render();
  }
  • Using the dropdown property pane control in spfx, render the list web part property. Change the getPropertyPaneConfiguration() function in the ListItemsWebPart class to render the departmentName web part property using the dropdown property pane control.
protected getPropertyPaneConfiguration(): IPropertyPaneConfiguration {
    return {
      pages: [
        {
          header: {
            description: strings.PropertyPaneDescription
          },
          groups: [
            {
              groupName: strings.BasicGroupName,
              groupFields: [
                new PropertyPaneDropdown('DepartmentName', {
                  label: strings.ListFieldLabel,
                  loadOptions: this.loadLists.bind(this),
                  onPropertyChange: this.onChangeList.bind(this),
                  selectedKey: this.properties.departmentName
                })
              ]
            }
          ]
        }
      ]
    };
  }

Here you can refer to the full code of ListItemsWebPart.ts file :

import * as React from 'react';
import * as ReactDom from 'react-dom';
import { Version } from '@microsoft/sp-core-library';
import {
  IPropertyPaneConfiguration,
  PropertyPaneTextField
} from '@microsoft/sp-property-pane';
import { BaseClientSideWebPart } from '@microsoft/sp-webpart-base';
import { IReadonlyTheme } from '@microsoft/sp-component-base';

import * as strings from 'ListItemsWebPartStrings';
import ListItems from './components/ListItems';
import { IListItemsProps } from './components/IListItemsProps';
import { PropertyPaneDropdown } from '../../controls/AsyncDropdownPropertyPane/PropertyPaneAsyncDropdown/PropertyPaneDropdown';
import { IDropdownOption } from 'office-ui-fabric-react/lib/components/Dropdown';
import { update, get } from '@microsoft/sp-lodash-subset';
export interface IListItemsWebPartProps {
  description: string;
  departmentName: string;
}

export default class ListItemsWebPart extends BaseClientSideWebPart<IListItemsWebPartProps> {

  private _isDarkTheme: boolean = false;
  private _environmentMessage: string = '';

  public render(): void {
    const element: React.ReactElement<IListItemsProps> = React.createElement(
      ListItems,
      {
        departmentName: this.properties.departmentName,
        description: this.properties.description,
        isDarkTheme: this._isDarkTheme,
        environmentMessage: this._environmentMessage,
        hasTeamsContext: !!this.context.sdks.microsoftTeams,
        userDisplayName: this.context.pageContext.user.displayName
      }
    );

    ReactDom.render(element, this.domElement);
  }

  protected onInit(): Promise<void> {
    this._environmentMessage = this._getEnvironmentMessage();

    return super.onInit();
  }

  private _getEnvironmentMessage(): string {
    if (!!this.context.sdks.microsoftTeams) { // running in Teams
      return this.context.isServedFromLocalhost ? strings.AppLocalEnvironmentTeams : strings.AppTeamsTabEnvironment;
    }

    return this.context.isServedFromLocalhost ? strings.AppLocalEnvironmentSharePoint : strings.AppSharePointEnvironment;
  }

  protected onThemeChanged(currentTheme: IReadonlyTheme | undefined): void {
    if (!currentTheme) {
      return;
    }

    this._isDarkTheme = !!currentTheme.isInverted;
    const {
      semanticColors
    } = currentTheme;

    if (semanticColors) {
      this.domElement.style.setProperty('--bodyText', semanticColors.bodyText || null);
      this.domElement.style.setProperty('--link', semanticColors.link || null);
      this.domElement.style.setProperty('--linkHovered', semanticColors.linkHovered || null);
    }

  }
  private loadLists(): Promise<IDropdownOption[]> {
    return new Promise<IDropdownOption[]>((resolve: (options: IDropdownOption[]) => void, reject: (error: any) => void) => {
      setTimeout(() => {
        resolve([{
          key: 'finance',
          text: 'Finance'
        },
          {
            key: 'development',
            text: 'Development'
          }]);
      }, 3000);
    });
  }
  private onChangeList(propertyPath: string, newValue: any): void {
    const oldValue: any = get(this.properties, propertyPath);
    // store new value in web part properties
    update(this.properties, propertyPath, (): any => { return newValue; });
    // refresh web part
    this.render();
  }

  protected onDispose(): void {
    ReactDom.unmountComponentAtNode(this.domElement);
  }

  protected get dataVersion(): Version {
    return Version.parse('1.0');
  }

  protected getPropertyPaneConfiguration(): IPropertyPaneConfiguration {
    return {
      pages: [
        {
          header: {
            description: strings.PropertyPaneDescription
          },
          groups: [
            {
              groupName: strings.BasicGroupName,
              groupFields: [
                new PropertyPaneDropdown('DepartmentName', {
                  label: strings.ListFieldLabel,
                  loadOptions: this.loadLists.bind(this),
                  onPropertyChange: this.onChangeList.bind(this),
                  selectedKey: this.properties.departmentName
                })
              ]
            }
          ]
        }
      ]
    };
  }
}

Now we have added a custom control dropdown to the properties in the web part property pane, so run the below command for testing.

gulp serve
Custom property pane in spfx
Custom property pane in spfx

Download SPFx Solution

To use this solution, download the solution file, unzip it and run the below command.

npm i

Conclusion

In this spfx tutorial, we end up adding a custom control dropdown to the properties in the web part property pane in the SharePoint framework. So here is the information we have covered :

  • What is the property pane in spfx?
  • What is the use of the property pane in spfx?
  • Custom property pane controls spfx
    • Create a web part property to store the selected list
    • How to define dropdown control in the Property pane in spfx
    • Add a property pane dropdown control React component
    • Add dropdown control to the property pane
    • Use the dropdown property pane control inside the web part

You may also like the following SPFx tutorials:

>