logo
Published on

Gathering collection of data in property page using PnP PropertyFieldCollectionData control in SPFx

This article walks you through how to use the PnP PropertyFieldCollectionData control to manage multiple entries (such as links, URLs, or boolean values) directly within the property pane of an SPFx web part.

The control allows you to insert, edit, and delete multiple rows of data such as titles, links, and options — making it ideal for creating repeatable link collections or configuration sets.


⚙️ Install the Required PnP Package

Install the PnP property controls package using:

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

🧩 Client-Side Web Part Class

SpfxPnpPropertyfieldcollectiondataWebPart.ts

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 * as strings from 'SpfxPnpPropertyfieldcollectiondataWebPartStrings';
import SpfxPnpPropertyfieldcollectiondata from './components/SpfxPnpPropertyfieldcollectiondata';
import { ISpfxPnpPropertyfieldcollectiondataProps } from './components/ISpfxPnpPropertyfieldcollectiondataProps';
 
import { PropertyFieldCollectionData, CustomCollectionFieldType } from '@pnp/spfx-property-controls/lib/PropertyFieldCollectionData';
 
export interface ISpfxPnpPropertyfieldcollectiondataWebPartProps {
  description: string;
  collectionData: any[];
}
 
export default class SpfxPnpPropertyfieldcollectiondataWebPart extends BaseClientSideWebPart<ISpfxPnpPropertyfieldcollectiondataWebPartProps> {
  public render(): void {
    const element: React.ReactElement<ISpfxPnpPropertyfieldcollectiondataProps> = React.createElement(
      SpfxPnpPropertyfieldcollectiondata,
      {
        description: this.properties.description,
        listinformation: this.properties.collectionData
      }
    );
    ReactDom.render(element, this.domElement);
  }
 
  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
                }),
                PropertyFieldCollectionData("collectionData", {
                  key: "collectionData",
                  label: "Links",
                  panelHeader: "links",
                  manageBtnLabel: "Manage links",
                  value: this.properties.collectionData,
                  fields: [
                    {
                      id: "LinkName",
                      title: "Name",
                      type: CustomCollectionFieldType.string,
                      required: true
                    },
                    {
                      id: "URL",
                      title: "URL",
                      type: CustomCollectionFieldType.string
                    },
                    {
                      id: "Openinnewtab",
                      title: "Open in new tab",
                      type: CustomCollectionFieldType.boolean
                    }
                  ],
                  disabled: false
                })
              ]
            }
          ]
        }
      ]
    };
  }
}

⚡ React Component

SpfxPnpPropertyfieldcollectiondata.tsx

import * as React from 'react';
import styles from './SpfxPnpPropertyfieldcollectiondata.module.scss';
import { ISpfxPnpPropertyfieldcollectiondataProps } from './ISpfxPnpPropertyfieldcollectiondataProps';
import { Link } from 'office-ui-fabric-react/lib/Link';
 
export default class SpfxPnpPropertyfieldcollectiondata extends React.Component<ISpfxPnpPropertyfieldcollectiondataProps, {}> {
  public render(): React.ReactElement<ISpfxPnpPropertyfieldcollectiondataProps> {
    return (
      <div className={styles.spfxPnpPropertyfieldcollectiondata}>
        <h2>{this.props.description}</h2>
        {this.props.listinformation &&
          <ul>
            {this.props.listinformation.map(function (linkinfo, i) {
              return <li><Link target={linkinfo.Openinnewtab ? '_blank' : '_self'} href={linkinfo.URL}>{linkinfo.LinkName}</Link></li>
            })}
          </ul>
        }
      </div>
    );
  }
}

🧾 Explanation

  • The PropertyFieldCollectionData control provides a custom property pane that lets you add, edit, and delete multiple rows of structured data.
  • Each column can represent text, boolean, dropdown, or number fields.
  • The collected data can be accessed inside your component via this.properties.collectionData.

🚀 Build and Deploy

To verify the build:

gulp build

Then bundle and package:

gulp bundle --ship
gulp package-solution --ship

Upload the .sppkg file from the sharepoint/solution folder to your App Catalog and deploy the solution.


📂 GitHub Source

View full SPFx project on GitHub:Gathering collection of data in property page using PnP PropertyFieldCollectionData control in SPFx

GitHub

✅ Summary

The PnP PropertyFieldCollectionData control is perfect for scenarios where you want to manage repeatable structured data right within your web part’s property pane — for example, managing lists of links, contacts, or configuration values without needing external storage.

Calendar IconBook a demo