Unlike the native PropertyPaneTextField, this control returns a structured date value instead of a plain string. It can be configured to display only a date or both a date and a time.

In this example, we will create a Property Pane field that allows the web part author to select a date and time using a 12-hour clock.

The selected value will then be passed from the web part properties to a React component and displayed inside the web part.

Using PropertyFieldDateTimePicker in an SPFx Web Part

The PropertyFieldDateTimePicker control provides a date and time selector that can be added to the Property Pane of a SharePoint Framework web part.

Unlike the native PropertyPaneTextField, this control returns a structured date value instead of a plain string. It can be configured to display only a date or both a date and a time.

In this example, we will create a Property Pane field that allows the web part author to select a date and time using a 12-hour clock.

The selected value will then be passed from the web part properties to a React component and displayed inside the web part.

The control is part of the reusable PnP SPFx Property Controls library. (PNP)


Install the PnP SPFx Property Controls package

Run the following command from the root directory of your existing SPFx solution:

npm install @pnp/spfx-property-controls --save

After installing the package, restore the remaining project dependencies:

npm install

Import the PropertyFieldDateTimePicker control

The control, its conventions and its value interface can be imported from the same module:

import {
PropertyFieldDateTimePicker,
DateConvention,
TimeConvention,
IDateTimeFieldValue
} from '@pnp/spfx-property-controls/lib/PropertyFieldDateTimePicker';

The following elements are used:

  • PropertyFieldDateTimePicker creates the Property Pane field.
  • DateConvention defines whether the control displays only a date or a date and time.
  • TimeConvention defines whether the control uses a 12-hour or 24-hour clock.
  • IDateTimeFieldValue represents the selected value.

Define the web part properties

The web part needs a property to store the selected date and time.

export interface IPropertyFieldDateTimePickerWpWebPartProps {
description: string;
datetime: IDateTimeFieldValue;
}

The datetime property must use IDateTimeFieldValue.

It should not be declared as a string or Date because the PnP control returns an object containing the selected date and its formatted display value.


Complete web part code

Open the main web part file:

src/webparts/propertyFieldDateTimePickerWp/PropertyFieldDateTimePickerWpWebPart.ts

Replace its contents with the following code:

import * as React from 'react';
import * as ReactDom from 'react-dom';
import { Version } from '@microsoft/sp-core-library';
import {
type 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 'PropertyFieldDateTimePickerWpWebPartStrings';
import PropertyFieldDateTimePickerWp
from './components/PropertyFieldDateTimePickerWp';
import {
IPropertyFieldDateTimePickerWpProps
} from './components/IPropertyFieldDateTimePickerWpProps';
import {
PropertyFieldDateTimePicker,
DateConvention,
TimeConvention,
IDateTimeFieldValue
} from '@pnp/spfx-property-controls/lib/PropertyFieldDateTimePicker';
export interface IPropertyFieldDateTimePickerWpWebPartProps {
description: string;
datetime: IDateTimeFieldValue;
}
export default class PropertyFieldDateTimePickerWpWebPart
extends BaseClientSideWebPart<IPropertyFieldDateTimePickerWpWebPartProps> {
private _isDarkTheme: boolean = false;
private _environmentMessage: string = '';
public render(): void {
const element:
React.ReactElement<IPropertyFieldDateTimePickerWpProps> =
React.createElement(
PropertyFieldDateTimePickerWp,
{
description: this.properties.description,
isDarkTheme: this._isDarkTheme,
environmentMessage: this._environmentMessage,
userDisplayName:
this.context.pageContext.user.displayName,
datetime: this.properties.datetime
}
);
ReactDom.render(
element,
this.domElement
);
}
protected onInit(): Promise<void> {
return this._getEnvironmentMessage()
.then((message: string): void => {
this._environmentMessage = message;
});
}
private _getEnvironmentMessage(): Promise<string> {
if (this.context.sdks.microsoftTeams) {
return this.context.sdks.microsoftTeams
.teamsJs.app
.getContext()
.then((context): string => {
let environmentMessage: string = '';
switch (context.app.host.name) {
case 'Office':
environmentMessage =
this.context.isServedFromLocalhost
? strings.AppLocalEnvironmentOffice
: strings.AppOfficeEnvironment;
break;
case 'Outlook':
environmentMessage =
this.context.isServedFromLocalhost
? strings.AppLocalEnvironmentOutlook
: strings.AppOutlookEnvironment;
break;
case 'Teams':
case 'TeamsModern':
environmentMessage =
this.context.isServedFromLocalhost
? strings.AppLocalEnvironmentTeams
: strings.AppTeamsTabEnvironment;
break;
default:
environmentMessage =
strings.UnknownEnvironment;
}
return environmentMessage;
});
}
return Promise.resolve(
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
);
}
}
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: [
PropertyPaneTextField(
'description',
{
label:
strings.DescriptionFieldLabel
}
),
PropertyFieldDateTimePicker(
'datetime',
{
label:
'Select the date and time',
initialDate:
this.properties.datetime,
dateConvention:
DateConvention.DateTime,
timeConvention:
TimeConvention.Hours12,
onPropertyChange:
this.onPropertyPaneFieldChanged,
properties:
this.properties,
onGetErrorMessage:
undefined,
deferredValidationTime:
0,
key:
'dateTimeFieldId',
showLabels:
false
}
)
]
}
]
}
]
};
}
}

Understanding the Property Pane group

The control is added to the groupFields collection of a Property Pane group:

groups: [
{
groupName: strings.BasicGroupName,
groupFields: [
PropertyPaneTextField(
'description',
{
label: strings.DescriptionFieldLabel
}
),
PropertyFieldDateTimePicker(
'datetime',
{
// Control configuration
}
)
]
}
]

The groupName property defines the group title displayed in the Property Pane.

The groupFields array contains the fields rendered inside that group.

In this example, the group contains:

  1. A native SPFx PropertyPaneTextField.
  2. A PnP PropertyFieldDateTimePicker.

The PnP control documentation specifies that the custom field must be added to the groupFields collection of the web part Property Pane configuration. (PNP)


Configure the PropertyFieldDateTimePicker

The control configuration is:

PropertyFieldDateTimePicker(
'datetime',
{
label: 'Select the date and time',
initialDate: this.properties.datetime,
dateConvention: DateConvention.DateTime,
timeConvention: TimeConvention.Hours12,
onPropertyChange:
this.onPropertyPaneFieldChanged,
properties: this.properties,
onGetErrorMessage: undefined,
deferredValidationTime: 0,
key: 'dateTimeFieldId',
showLabels: false
}
)

The first argument is the web part property name:

'datetime'

This connects the control to:

this.properties.datetime

When the user changes the selected date, the new value is stored in that web part property.


The label property

label: 'Select the date and time'

The label property defines the text displayed above the Property Pane control.


The initialDate property

initialDate: this.properties.datetime

The initialDate property provides the value that should initially be displayed by the control.

When the web part is edited again, the previously saved value is passed back to the control.

This value must use the IDateTimeFieldValue interface.


The dateConvention property

dateConvention: DateConvention.DateTime

The date convention controls whether the picker displays only a date or both date and time.

To display only the date, use:

dateConvention: DateConvention.Date

To display both date and time, use:

dateConvention: DateConvention.DateTime

The control officially supports date-only and date-and-time configurations. (PNP)


The timeConvention property

timeConvention: TimeConvention.Hours12

The time convention defines how the time is displayed.

For a 12-hour clock, use:

timeConvention: TimeConvention.Hours12

For a 24-hour clock, use:

timeConvention: TimeConvention.Hours24

The onPropertyChange property

onPropertyChange:
this.onPropertyPaneFieldChanged

This callback informs the SPFx Property Pane that the property value has changed.

It allows SPFx to update:

this.properties.datetime

Without this connection, the control would not correctly participate in the standard SPFx property update process.


The properties property

properties: this.properties

This provides the complete web part property object to the PnP control.

The control uses this object together with onPropertyChange to update the selected property.


The validation properties

onGetErrorMessage: undefined,
deferredValidationTime: 0

The onGetErrorMessage property can be used to implement custom validation.

In this example, no validation function is provided:

onGetErrorMessage: undefined

The deferredValidationTime property defines the delay before validation begins.

Because no validation is required, it is set to zero:

deferredValidationTime: 0

The key property

key: 'dateTimeFieldId'

The key uniquely identifies the Property Pane control.

Each custom Property Pane control should have a stable and unique key.


The showLabels property

showLabels: false

This property controls whether the internal date and time labels are displayed.

In this example, the additional labels are hidden.


Create the React props interface

Open:

src/webparts/propertyFieldDateTimePickerWp/components/IPropertyFieldDateTimePickerWpProps.ts

Add the following code:

import {
IDateTimeFieldValue
} from '@pnp/spfx-property-controls/lib/PropertyFieldDateTimePicker';
export interface IPropertyFieldDateTimePickerWpProps {
description: string;
isDarkTheme: boolean;
environmentMessage: string;
userDisplayName: string;
datetime?: IDateTimeFieldValue;
}

The datetime property is optional because the web part may not have a selected date when it is added to the page for the first time.

datetime?: IDateTimeFieldValue;

Importing IDateTimeFieldValue from the specific control module also keeps the import consistent with the web part file.


Create the React component

Open:

src/webparts/propertyFieldDateTimePickerWp/components/PropertyFieldDateTimePickerWp.tsx

Use the following code:

import * as React from 'react';
import {
IPropertyFieldDateTimePickerWpProps
} from './IPropertyFieldDateTimePickerWpProps';
const PropertyFieldDateTimePickerWp:
React.FunctionComponent<IPropertyFieldDateTimePickerWpProps> = (
props
) => {
return (
<div>
<h1>
Property Field Date Time Picker Web Part
</h1>
<p>
This is a sample web part that demonstrates
the use of the PropertyFieldDateTimePicker
control.
</p>
<p>
Description: {props.description}
</p>
<p>
Is Dark Theme:{' '}
{props.isDarkTheme ? 'Yes' : 'No'}
</p>
<p>
Environment Message:{' '}
{props.environmentMessage}
</p>
<p>
User Display Name:{' '}
{props.userDisplayName}
</p>
<p>
Selected Date Time:{' '}
{
props.datetime
? props.datetime.displayValue
: 'No date selected'
}
</p>
</div>
);
};
export default PropertyFieldDateTimePickerWp;

Display the selected date

The selected formatted value is available through:

props.datetime.displayValue

Because a date may not have been selected yet, the component checks whether the property contains a value:

{
props.datetime
? props.datetime.displayValue
: 'No date selected'
}

This prevents runtime errors when the web part is rendered before the user configures the control.

The explicit toString() call is unnecessary because displayValue can be rendered directly:

props.datetime.displayValue

Understanding IDateTimeFieldValue

The PropertyFieldDateTimePicker does not return only a formatted string.

It returns an IDateTimeFieldValue object.

The two most useful values are:

datetime.value

and:

datetime.displayValue

The value property represents the actual JavaScript date value.

The displayValue property represents the date and time formatted for display.

For example:

<p>
Formatted value:
{props.datetime?.displayValue}
</p>

To work directly with the JavaScript Date object:

<p>
Date object:
{props.datetime?.value.toLocaleString()}
</p>

How the data flows through the web part

The Property Pane control writes the selected value to:

this.properties.datetime

The web part passes that value to the React component:

datetime: this.properties.datetime

The React interface receives it:

datetime?: IDateTimeFieldValue;

The component displays the formatted value:

props.datetime.displayValue

The complete flow is:

PropertyFieldDateTimePicker
this.properties.datetime
React.createElement properties
IPropertyFieldDateTimePickerWpProps
React component
datetime.displayValue

Important correction: do not use an empty string

The following fallback should not be used:

datetime: this.properties.datetime || ''

The problem is that datetime expects:

IDateTimeFieldValue

but the fallback provides:

string

These types are incompatible.

Use:

datetime: this.properties.datetime

Then declare the React property as optional:

datetime?: IDateTimeFieldValue;

The React component can handle the undefined state safely.


Important correction: remove the duplicate interface

The following interface is not required:

export interface IPropertyControlsTestWebPartProps {
datetime: IDateTimeFieldValue;
}

The web part already uses:

export interface IPropertyFieldDateTimePickerWpWebPartProps {
description: string;
datetime: IDateTimeFieldValue;
}

Keeping both interfaces creates unnecessary duplication and can make the code more confusing.


Optional default date

A default value can be initialized inside onInit.

protected onInit(): Promise<void> {
if (!this.properties.datetime) {
const currentDate: Date = new Date();
this.properties.datetime = {
value: currentDate,
displayValue:
currentDate.toLocaleString()
};
}
return this._getEnvironmentMessage()
.then((message: string): void => {
this._environmentMessage = message;
});
}

This is optional.

Without a default value, the control simply starts without a selected date.


Use a 24-hour clock

To change the control to a 24-hour format, replace:

timeConvention: TimeConvention.Hours12

with:

timeConvention: TimeConvention.Hours24

Use date only

To remove the time selection, replace:

dateConvention: DateConvention.DateTime

with:

dateConvention: DateConvention.Date

The configuration would become:

PropertyFieldDateTimePicker(
'datetime',
{
label: 'Select a date',
initialDate: this.properties.datetime,
dateConvention: DateConvention.Date,
timeConvention: TimeConvention.Hours24,
onPropertyChange:
this.onPropertyPaneFieldChanged,
properties: this.properties,
onGetErrorMessage: undefined,
deferredValidationTime: 0,
key: 'dateFieldId',
showLabels: false
}
)

Run the web part

Start the SPFx development server using Heft:

heft start

Open the SharePoint hosted workbench, add the web part and edit its properties.

The Property Pane will display:

Select the date and time

After selecting a value, the control stores it in:

this.properties.datetime

The React component then displays:

Selected Date Time: [formatted date and time]

Common TypeScript problem

A common error occurs when a string is assigned to IDateTimeFieldValue.

Example of incorrect code:

datetime: this.properties.datetime || ''

Possible TypeScript result:

Type 'string | IDateTimeFieldValue'
is not assignable to type
'IDateTimeFieldValue'

Correct code:

datetime: this.properties.datetime

And in the React props interface:

datetime?: IDateTimeFieldValue;

Final result

The web part now contains:

  • A native description text field.
  • A PnP date and time selector.
  • A value stored in the web part properties.
  • A strongly typed IDateTimeFieldValue.
  • A React component that displays the selected date.
  • Support for date-only or date-and-time configurations.
  • Support for 12-hour or 24-hour time formats.

The most important part of this implementation is preserving the correct type throughout the complete data flow:

IDateTimeFieldValue

The value should remain strongly typed from the Property Pane configuration through the web part properties and into the React component.


Official documentation

PropertyFieldDateTimePicker:

PnP SPFx Property Controls:

The official documentation describes the control as a date and time picker for SPFx Property Panes and provides configurations for date-only and date-and-time selection. (PNP)

This article keeps your original demonstration structure while correcting the IDateTimeFieldValue typing and the unsafe empty-string fallback.

Edvaldo Guimrães Filho Avatar

Published by