DEV Community

Guido Zambarda
Guido Zambarda

Posted on • Originally published at iamguidozam.blog on

Connect SharePoint Framework web parts using dynamic data

You probably already know what are SharePoint Framework (SPFx) web parts but do you know that you can connect two web parts dynamically?

In a nutshell the provider web part needs to implement the interface IDynamicDataCallables to define which are the dynamic properties to expose, the consumer web part will define the receiver properties in the property pane using the PropertyPaneDynamicField and can access the properties values using the tryGetValue method.

The result

I prepared a sample (you can find the link at the end of this post) to show how web parts with dynamic data work.

In the sample there are two web parts:

  • the “Source web part” which allows the user to insert data and provides it to the other web part.
  • the “Target web part” which receives and displays the specified data.

These are the two web parts, not configured and not filled in:

To connect the web parts, SPFx enable the selection of the source for a specific property in the receiver web part, in the following image you can see the property pane of the “Target web part” and the properties that the user can select:

When the user clicks on any of the drop downs will see a list of the available sources to which the property can be connected, in this case the possibilities are “Page environment” and “Source”, the second one is the connection name of the “Source web part”:

Once that the source has been specified it will be required that the user select the property of the source to be used with the current property. For example in the following image the user is configuring the “First Name” and will select the first option from the drop down:

Aside of the custom source there is also the possibility to select “Page environment” which allows the selection of different page context properties, those properties are:

  • Site properties
  • Current user information
  • Query string
  • Search

Each of the page environment’ properties can have an additional property selection, for example when selecting the “Current user information” the user can select one of the following options:

  • User Name
  • User email
  • Login mail

To enable the selection of the properties another drop down will be added, so with the current user information option it will become like the following image:

After all the fields in the property pane are selected the web parts will display as following, where the only field that has data will be the “User name” because it’s the only one that will be retrieved from the page environment, the others are bind to the input fields that are currently empty:

When the user insert data in the input fields the linked field will be automatically and dinamically updated:

The code

Provider web part

Starting with the provider web part it needs to implement the IDynamicDataCallablesinterface and to use it the following import must be specified:

import { IDynamicDataPropertyDefinition, IDynamicDataCallables,} from "@microsoft/sp-dynamic-data";
Enter fullscreen mode Exit fullscreen mode

Once imported, two of the interface methods must be implemented and those are:

  • getPropertyDefinitions: returns the properties that the web part expose.
  • getPropertyValue: returns the value of a specific exposed property.

In the sample the getPropertyDefinitions is implemented as following:

public getPropertyDefinitions(): ReadonlyArray<IDynamicDataPropertyDefinition> { return [{ id: Constants.FirstNamePropertyId, title: strings.FirstName, }, { id: Constants.LastNamePropertyId, title: strings.LastName, }, { id: Constants.PreferencesPropertyId, title: strings.Preferences, }];}
Enter fullscreen mode Exit fullscreen mode

In the previous code each of the objects in the array represent one of the exposed properties.

NB : the property that handle the Page environment value will not be specified in the source web part but only in the target one.

The second required method is implemented as following:

public getPropertyValue(propertyId: string): string | IPreferences { switch (propertyId) { case Constants.FirstNamePropertyId:  return this._firstName; case Constants.LastNamePropertyId:  return this._lastName; case Constants.PreferencesPropertyId:    return this._preferences; } throw new Error(strings.BadPropertyId);}
Enter fullscreen mode Exit fullscreen mode

The getPropertyValue method returns the value for the propertyId specified as the input parameter. In the sample the Constants class contains the name for the various exposed properties so it’s easier to use the correct property name and to avoid any possible writing mistake during the development process.

After implemented the IDynamicDataCallables interface there are a few more steps to take.

In the onInit method it’s necessary to register the current web part as data source for the dynamic data source manager, this is achieved with the following code:

protected async onInit(): Promise<void> { this.context .dynamicDataSourceManager .initializeSource(this);}
Enter fullscreen mode Exit fullscreen mode

The last step is to bind the input element with a method that notify the dynamicDataSourceManager of the property change. Continuing with the sample code I wrote, in the source web part, I defined a method for each of the dynamic properties, the following is the one for the first name property:

private _firstNameChanged = (firstName: string): void => { this._firstName = firstName; // notify subscribers that the first name has changed this.context .dynamicDataSourceManager .notifyPropertyChanged(Constants.FirstNamePropertyId);};
Enter fullscreen mode Exit fullscreen mode

NB : each of the dynamic properties that are exposed will need to have it’s own notifyPropertyChanged with the id of the specific property.

The methods to notify the change will be passed to the web part control and will be used in the onChange (or equivalent) event of the input fields, sticking with the first name property this is the implementation of the input control:

<TextField label={strings.FirstName} onChange={(ev, newValue) => this.props.onFirstNameChanged(newValue)} />
Enter fullscreen mode Exit fullscreen mode

And this is all for the source web part, the next step will be to proceed with the target web part.

Target web part

The target (or consumer) web part does not need any interface but the properties will necessary be of type DynamicProperty<T>.

The DynamicProperty type will be imported from the @microsoft/sp-component-base package:

import { DynamicProperty } from '@microsoft/sp-component-base';
Enter fullscreen mode Exit fullscreen mode

So in the target web part of the sample the properties are defined as the following:

export interface ITargetWebPartProps { firstName: DynamicProperty<string>; lastName: DynamicProperty<string>; preferences: DynamicProperty<IPreferences>; userName: DynamicProperty<string>;}
Enter fullscreen mode Exit fullscreen mode

To bind the properties in the property pane it’s required a specific property pane method which is the PropertyPaneDynamicField, to use it a new import must be added:

import { PropertyPaneDynamicField} from '@microsoft/sp-property-pane';
Enter fullscreen mode Exit fullscreen mode

And then use it in the property pane as following:

protected getPropertyPaneConfiguration(): IPropertyPaneConfiguration { return { pages: [{ header: { description: strings.PropertyPaneDescription, }, groups: [{ groupName: strings.BasicGroupName, groupFields: [PropertyPaneDynamicField("firstName", { label: strings.FirstName, }), PropertyPaneDynamicField("lastName", { label: strings.LastName, }),], }, { groupName: strings.ComplexGroupName, groupFields: [PropertyPaneDynamicField("preferences", { label: strings.Preferences, }),], }, { groupName: strings.PageEnvironmentGroupName, groupFields: [PropertyPaneDynamicField("userName", { label: strings.UserName, }),], }, ], }, ], };}
Enter fullscreen mode Exit fullscreen mode

At this point, to use the web part property in the control and in order to retrieve it’s value, it will be necessary to use the tryGetValue method for each of the dynamic property:

const { firstName, lastName, preferences, userName } = this.props;// Get the value from the dynamic propertiesconst firstNameValue = firstName?.tryGetValue();const lastNameValue = lastName?.tryGetValue();const preferencesValue = preferences?.tryGetValue();const userNameValue = userName?.tryGetValue();
Enter fullscreen mode Exit fullscreen mode

The only thing that remains to do is to add the web parts in a page and connect them using the property pane of the target web part.

Conclusions

Connecting two or more web parts can be useful, for example you can have a source web part that displays some search filters and then a consumer web part that use those filters to display some data, a very good example can be the PnP modern search solution.

If you want to check out the code from the sample you can find it in the Microsoft sample solution gallery at this link.

Hope this helps!

Top comments (0)