Connected SharePoint Framework (SPFx) Webparts Part 1

One of the key use cases for traditional SharePoint webparts is to have a webpart that allows users to enter some sort of input, causing another webpart to respond in some way. Out of the box SPFx webparts do not allow for this, however there are ways to achieve connected SharePoint Framework (SPFx) webparts. The absolute basics for just the communication piece of this puzzle are included in a reference webpart project on the team’s GitHub site here. There are in fact two samples that use events to communicate between webparts, the react-events-aggregator and the react-rxjs-event-emitter, the main difference being that the former uses out of the box tools to accomplish the event publication and subscription, and intrinsically uses the observable pattern, whereas the latter uses the rx-lite library to achieve this result.

In this blog post I will build on the former sample, react-events-aggregator to show something more resembling a real use case and highlight the following aspects of developing SPFx webparts using React:

  • Creating SPFx webparts that can communicate from one to the other in order for the second one to display some useful or desired information. The main mechanism leveraged for this to take place is the pub-sub model provided by the eventAggregator property of the context of a webpart. I take it a little further than the sample project on the team’s GitHub by defining additional EventData types.
  • How to leverage the React lifecycle events to manage the React component. By knowing what these events are, the order and frequency of firing, one can build more robust and responsive webparts. The thing here to focus on for traditional SharePoint webpart developers, is that in place of the synchronous /async events(-ing and –ed events), React uses a Will/Did model.
  • Show how the composability of React components simplifies SPFx development. In the sample project for this webpart there are two components in a parent child type relationship, with the child delegating some event handling to the parent. Leveraging this feature one can build generic components for reusability.
  • Show how to use state with React components. For the most part the sample applications avoid the use of state, thereby allowing them to highlight a single aspect of SPFx webpart development. However state is a key part of React development. A React component can receive a props object containing a collection of properties for it to use in composing itself, or defining behaviour,  however these are meant to be immutable by the receiving component. By using state as a passed in collection, one can have a finer granularity of control, and responsiveness, of both the child and the parent components.

Now to the meat of the matter. I decided that I wanted a tool to list out some Git Ids, then to be able to see the repos associated with a given Id. To get started I ran the yo command twice from the same folder. The first time I named the solution ‘Git Tool’ then said I wanted a webpart named ‘Git Ids’ using React as the JavaScript library. The second time it did not prompt for the solution, and I chose to create a webpart named ‘Git Repos’ with React.

After opening the solution in VS Code the first thing I did was to rename the IGitIdsProps.ts to IGitIdsPropsAndState.ts, and the same to the IGitReposProps.ts. By defining interfaces for the state, as well as properties, I am able to avoid the double curly brace ({}) in the react component definition, have a tighter type safety and use the React constructors to work with the state in my components. Plus I thought having separate files for the state definitions seemed overkill. This is getting a little ahead of myself, so back to the webpart.ts files themselves.

The Git Ids Webpart

The next step is to determine how to get the Git Ids into my webpart to list them. First I add a string property to the webpart itself, GitIdsWebpart.ts, which, of course, includes the property pane configuration method. The idea is to get a comma delimited string which I could convert to an array. Optionally, one can add them to the localization strings, which I have done. Finally I added some default Ids in the manifest.json file. Before calling the react component from the webpart.ts, in the render method, I put the ids into a string array to be able to list them out. To accomplish this I have to add a property of type string array, named ids, in the IGitIdsProps interface.

Now one thing I want to illustrate is how to have components within another component, in a parent/child type relationship. This allows for greater reusability, so I will create a dropdown component to display the ids from which to choose one to display the repos. To accomplish this I add ReactDropdown.tsx and IReactDropdownPropsAndState.ts files. You may have noticed that the props file for the dropdown is named IReactDropdownPropsAndState. This is because I want to make the selected item from the dropdown to be, in effect, a non-immutable, property of the component, which is what state is for in the React universe. If you search the code you will see how this gets manipulated. As far as the (immutable) properties of the child dropdown component are concerned, I pass in a title, the description and string array of ids I got from the webpart code. I also pass in a reference to a function in the parent component, GitIds.tsx. This way I can handle in the parent, an event originating in the child component. This goes a long way towards advancing the reusability of the dropdown component.

React Down and Dirty

Rounding out the Git Ids side of things I add a constructor to the ReactDropdown component as follows:

constructor(props: IReactDropdownProps) {
super(props);
this.state = {
selected: '',
selectedIdx: -1
};
}

In addition I added some console.warn statements on the principal React lifecycle events so that the reader can see when in the process they occur. For the render method I added, along with the html select element, some coating to display wherever the dropdown is used with the one twist that within the select element there is a method that gets called that adds in the options thusly:

<select
id='gitIdsDdl'
className='ms-Dropdown-select'
onChange={this._selectedChanged.bind(this)}
ref='ddl'
>
{this._renderGitIds()}
</select>

React: Lifting Up State

This method simply iterates the items passed in as a (immutable) property and creates an option element from them. The final thing to do is to add the _selectedChanged method which simply calls the method on the parent added in as a property, passing along the selected text and index.

Now to bring it all together. To the GitIds class I add a constructor much like the one I added for the dropdown, plus the console statements. The state is the same as for the dropdown with one property for the selected text and another for the index. I also add the method, onSelectedChanged, that gets passed into the dropdown component in response to selecting an item in the dropdown. Finally in the componentDidUpdate lifecycle method I add the code that will broadcast the event.

In the onSelectedChanged method I set the new state for the component, but broadcast the event from the componentDidUpdate lifecycle event to illustrate how React processes things. Although I set the state values in the added method, those values are not shown in the React component immediately. With what I now have I can select an item and then see how the GitIds component has access to what was chosen in the child component ReactDropdown.

Now all I need to do is to broadcast that event, and build out a webpart containing a component that subscribes to that event to list out GitHub repos associated with the selected Id. I will leave that to part 2 of Connected SharePoint Framework (SPFx) Webparts

No Comments

Add a Comment