Introducing the Property Pane Portal [Part 1]

Audience: SPFx Reactjs developers.

My quest for an easier way to build and maintain Property Pane controls on the SharePoint Framework.

[Part 1] (this post) Rethinking the SPFx Property Pane controls

[Part 2] Sample 1: Fluent UI controls

[Part 3] Sample 2: PnP SPFx Controls

[Part 4] The concept: leveraging Reactjs Portal for SPFx

[Part 5] Diving into the code

[Part 6] Sample 3: Microsoft Graph Toolkit controls

A long due post…

Last year, I started doing more serious development work with the SharePoint Framework (SPFx).

I have been using JavaScript for 15 years, and got started with Reactjs in 2019, directly working with function components and hooks – rather than the traditional class components – as primary building blocks. My first Reactjs solutions were built on the Create React App toolchain. Transitioning to SPFx was easy, until I started building custom Property Pane forms. While the body of a SPFx Web Part behaves like any single page application, the Property Pane follows a very specific format. Let’s take a closer look.

Below an example of Property Pane taken from the Microsoft documentation. On the surface, it looks like a Web form allowing to set the Web Part properties.

When we crack the code open however, it doesn’t look like a regular client side form:

groupFields: [
PropertyPaneTextField('list', {
label: 'Select a list'
}),
PropertyPaneCheckbox('display', {
label: 'Display'
}),
PropertyPaneSlider('max', {
label: 'Max number of tasks'
})
]

(note: simplified code for illustration purposes only)

The controls are encapsulated in predefined functions. In a way, it’s as if each control was its own form.

It’s all fine, and even convenient, as long as stay within the boundaries of what the functions allow. But it falls short as soon as we require a little more advanced functionality, such as dynamic choices, conditional formatting, etc. For example, you might want to let the user pick a site, or a group, or a list item, and the available choices will naturally depend on the context.

SPFx has an answer to that: it allows us to build our own custom controls. The process however is very intricated, and needs to be followed for every custom control. If for example you wanted to leverage the Fluent UI controls in the Property Pane, you would have to maintain for each control a dedicated Property Pane version. In comparison, in the Web Part body, you would be able to use the Fluent UI library as is.

Such an approach is actually available in the PnP community. I had some opportunities to be involved in the testing of the library, and have discussions with some of its main developers (Alex Terentiev, Elio Struyf, Joel Rodrigues). Same deal, the team needs to maintain two instances in parallel: the regular Reactjs controls and the dedicated Property Pane controls.

When I started diving into the SPFx tutorial, I found out that each of these custom controls is made of two layers (diagram below): a base that anchors the control to the Property Pane, and then the core control itself that handles the user interface and functionality. The base gets in place first, then calls an onRender() method to summon the control. Each control includes an update() method to push changes back to the Web Part property bag.

This got me thinking. Could we in some way avoid the redundancy? And as a bonus, directly hook a regular Reactjs component in here? That’s what I pictured in the diagram below: a generic, reusable frame that could serve as host to any Reactjs control.

It took me a couple days to come up with a workable model (the “Property Pane Portal”), weeks to test it, and then months to start writing about it 😊. In the next episodes, I’ll share some samples of the PPP in action, and I’ll provide more details on the architecture and the code that supports it. The key ingredient is Reactjs Portals, which allow to beam an element to another part of the DOM.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s