Introducing the Property Pane Portal [Part 3]

Audience: SPFx Reactjs developers.

[Part 1] Rethinking the SPFx Property Pane controls

[Part 2] Sample 1: Fluent UI controls

[Part 3] (this post) 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

In part 2, I showcased the use of Fluent UI controls in the Property Pane. Now it’s the turn of the PnP SPFx Controls.

Today, the PnP portal on Github offers two sets of Reactjs controls for your SPFx solution:

These libraries are extremely useful, because they are targeted at Microsoft 365 users and offer controls that you wouldn’t get out-of-the-box in other control libraries, not even with Microsoft’s own Fluent UI. For example: SharePoint list picker, list item picker, or people picker. The only library I can think of that comes close is the Microsoft Graph Toolkit, which we’ll tackle in part 6 of this series.

Listen to Joel Rodrigues introducing the SPFx Reactjs Controls, starting at 26:15 in the August 2 episode of the Microsoft 365 Developer Podcast.

Now, the painful part is that you need two libraries, because the Property Pane cannot use the regular controls and requires its own dedicated property controls. This is what we intend to change with the Property Pane Portal: use the same sp-dev-fx-controls-react library not just for the Web Part body, but also for the Property Pane!

The general steps are the same as in part 2, with the use of PropertyPaneHost and PropertyPanePortal. The only difference is the control itself:

Note how the context gets passed to the components through a Reactjs Context Hook. Here again, just like for the example in part 2, the Property Pane Portal allows us to leverage all the usual Reactjs patterns. The benefit is not just to skip the sp-dev-fx-property-controls library, but also pave the way to richer forms allowing more dynamic styling or interaction across components.

See it for yourself with the Github sample. A sppkg package (for demo purposes only) is included if you are in a hurry 🙂

Introducing the Property Pane Portal [Part 2]

Audience: SPFx Reactjs developers.

[Part 1] Rethinking the SPFx Property Pane controls

[Part 2] (this post) 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

In part 1, I explained the objective of the Property Pane Portal: allow us to use any Reactjs controls library in the Property Pane. This post showcases the concept applied to the Microsoft Fluent UI Northstar controls. Here is a screenshot of the expected result for our Github sample:

To follow this post, a prerequisite is to be familiar with SPFx Reactjs and the default SPFx Property Pane. If you are only interested to test drive the Web Part, you can grab the sample sppkg file (demo purposes only) from Github.

In the Property Pane, each default control (text field in the example below) is generated by a built-in function (PropertyPaneTextField() in the example).

Let’s now see how the code in our Fluent UI Github sample differs.

With the Property Pane Portal technique, the generic function PropertyPaneHost() only generates the host of each control:

The Web Part property propertyPaneHosts serves as data store for the location of the hosts. It is attached to the Web Part (“this”) to ensure there is no collision, for example in case a page hosts multiple instances of the same SPFx Web Part.

The controls themselves are included in the React DOM, along with the regular components used in the Web Part body (screenshot below). Then the job of the Reactjs Portal is to beam them to the Property Pane.

You’ll find the CustomPropertyPane component in CustomPropertyPane.tsx:

The machinery that supports the PropertyPanePortal component and the propertyPaneHost function is hosted in the PPP folder, and should work with any Reactjs controls library. Parts 4 and 5 will explore the concept and code in more details. In the meantime, feel free to post questions in the comments below.

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.

Transitioning from classic Content Editor Web Part to modern

Audience: SharePoint admins, Citizen Developers.

The Content Editor Web Part (CEWP) was a pillar of Power User and Citizen Developer work on classic SharePoint. Countless posts on this blog are dedicated to it and its siblings, the Script Editor Web Part and the Page Viewer Web Part.

With the migration to modern, the CEWP is not available anymore and site owners have been looking for alternatives.

My first advice is to clearly understand what problem you are trying to address, and look at out-of-the-box options. For example, if you need to insert some HTML in the page, maybe the Markdown Web Part has you covered? If you are trying to trigger an action, maybe Power Automate or Power Apps could fit the bill?

There are still situations where there is no easy path forward. What if you just need light adjustments to styles in the page? What if you want a news-like layout, with text wrapped around an image, like in the example below?

Microsoft’s answer is the SharePoint Framework (SPFx). The SPFx allows us to build Client Side Web Parts to complement the out-of-the-box solutions.

Several developers have leveraged the SharePoint Framework (SPFx), to release a modern version of the CEWP. Just to name a couple, check out the spjs blog or the Microsoft 365 PnP community.

I have decided to publish my own version on github. It is the first of a series of Client Side Web Parts I plan to release in the next couple months. Note that it is still in preview (version 0.9), and – like any Client Side Web Part – you’ll need an admin to install it on your environment.

But why yet another solution when there are already several available?

Beyond just offering a patch, I have a plan in mind. You’ll notice that my solution is named “Dangerous Content Web Part“, rather than “modern CEWP”. The first objective is to pass the message, and alert users on the risk when using such a Web Part. The other intent is to start working with clients on a “Safe Content Web Part” to smoothly transition out of the danger zone. If you are interested, contact me!