Using the dynamic data capability, you can connect SharePoint Framework client-side web parts and extensions to each other and exchange information between the components. Official documentation contains great example on how to connect web parts using DynamicProperty web part properties that can consume values from other web part, or, generally, data source. In my case I want to connect web parts in "old-school" way - with events firing and handling. Moreover, I want "receiver" web part to handle event from multiple "senders". This blog post is based on Page Sections Navigation sample from SPFx web parts samples repository. So, the initial idea is to create a solution that allows to render page sections navigation on SharePoint modern page. If you think of such a solution one of possible implementations would be to have "master" web part that renders the navigation, and multiple "anchor" web parts that can be added by a user anywhere on the page. "Master" web part should know about all the anchors, their positions and titles to render navigation and handle navigation events. And this is actually doable using dynamic data capability. Let's start with "Anchor" web part implementation. I'll be partially skipping details of code to focus attention on Dynamic Data features and APIs. As I mentioned above, "anchor" web part should notify "master" web part about its title and position (or DOM element instead of position). To do that we need to do few things:
mark "anchor" web part as a "data source" - implement IDynamicDataCallables interface and two methods from this interface:
getPropertyDefinitions to return list of dynamic data properties
getPropertyValue to get the value of specified property
register the web part as a data source
notify the engine if any of dynamic properties has been changed
There are two ways to implement dynamic properties for the "anchor" web part: either implement two properties: title and domElement, or combine them in single object. I selected the second approach. First, let's declare IAnchorItem interface:
Next, implement the IDynamicDataCallables interface:
Next step is to register the web part as a data source using this.context.dynamicDataSourceManager.initializeSource. Let's do that in onInit method:
Now we can notify subscribers every time when title or DOM element has been changed using this.context.dynamicDataSourceManager.notifyPropertyChanged method. In provided sample I'm doing that based on events fired from React component:
Now let's work on "master" web part. In this web part we need to collect all "anchor" data sources (web parts registered as data sources) from the page and subscribe to the changes of anchor property. Two things to consider here:
The page can contain data sources other than "anchors". These data sources should not be processed by the "master" web part.
"anchors" data sources can be dynamically added/removed based on user's interaction.
Currently, there is no tutorial on how to correctly work with data sources. But there is an SharePoint Framework API Reference that will help us! And, in particular, DynamicDataProvider and DynamicDataSourceManager classes. The first one is exposed as this.context.dynamicDataProvider in web parts and allows to get all data sources from the page as well as register for the change of available data sources.
The second one is exposed as this.context.dynamicDataSourceManager in web parts and allows to register on properties' changes of specific data sources. Knowing the above API we can easily collect "anchor" data sources dynamically and register on "anchor" property change. First, let's add a field that will store current "anchors" on the page:
Next, let's create the method that will iterate through page's data sources, update _dataSources collection, and subscribe on "anchor" property change event:
The last part is to call this method when the "master" web part is being initialize and every time when data sources are being changed.
Conclusion
Connecting web part using SPFx Dynamic Data is simple. Here are configuration/implementation steps:
In sender:
Implement IDynamicDataCallables interface in a web part with two methods: getPropertyDefinitions and getPropertyValue
Register a web part as a Data Source using this.context.dynamicDataSourceManager.initializeSource
Notify subscriber that some of properties have been changed using this.context.dynamicDataSourceManager.notifyPropertyChanged
In receiver:
Use this.context.dynamicDataProvider.registerAvailableSourcesChanged and this.context.dynamicDataProvider.getAvailableSources to iterate through available page's data source and select the ones to work with
Use this.context.dynamicDataProvider.registerPropertyChanged to register event handlers for specific data sources and properties
The example from this post processes single event from one type of data source. But you can use the same API to process different properties, data sources, and also implement circle connections between web parts.
Comments