Two features of Office365 that I have fallen in love with are SharePoint Search and the new Modern Communication Sites (yay early adopters!). One of my biggest complaints always has been how using SharePoint's search box functionality takes you away from the pages you are currently on. I've always been keen on getting relevant content to my user's using SharePoint Search or using Microsoft Graph as soon as they land on the page and then subsquently provide a means for the user to interact with the data or even search on the data, without having to navigate outside the current page into a completely new UI. This is why I built an inline search webpart using SPFx.
Here is my proof of concept for this webpart. This webpart is built using SPFx, ReactJs, Fabric UI and leverages the SharePoint Search API. In my initial design, I only have one template -- Document Card. My plan in the future is to allow user's select a different template through the WebPart properties.
There are obvious downsides to building out an inline-search mechanism for my pages, that is, currently I do not have the same functionality of a standard search page. An example below is the Out of the box search page, which provides me with more options to interact with my search results. I can search by site, by file types and other filters (with more to come).
While at this moment, the OOTB search page does provide a bit more flexibilty than my current webpart... I am planning on building a set of refiners that a user could use to filter by managed properties on their content.
So let's get started on how this webpart came together.
For this webpart, I have built a few interfaces to represent the data that is coming back from my Service (which calls the Search API). Because I am using search, I wanted a model that would represent my search result object.
SPResponse.ts
SPResponse.ts is the object representation of a SharePoint Search API Response
ISearchResult.ts
ISearchResult is the interface to store my individual response items back. These values represent the data you see on each individual card in the first picture above.
SPSearchService.ts
SPSearchService.ts is the core search functionality with one method "get" which takes two parameters, a webpart context (to get current site url) and the search query (which will come from the search box). I use the provided spHttpClient which comes from @microscot/sp-http.
So at this point, what we have is a search service that will execute a query against the REST API and populate an array of ISearchResults.
The implementation of my webpart is quite simple, however it is using 3 different React components to create the UI. In my base webpart component container I have constructed the following render().
You'll notice a couple things to start at the top of the ts file. I am importing from a ton of places. I am importing from React (because this is a react webpart), but I am also importing from office-ui-fabric so I can use the FabricUI React components (searchbox, documentcard, list,listitem). The last import statements are my modules for my interfaces and my search service that I will use on execution of a search in the search box.
You should also notice a couple other things, on line 16 I am binding my handleSearch function, to the current scope. This function is called on line 26 on, "onSearch" event of my React searchbox, passing in the current value of the search box. If you look at the handleSearch function on line 36, you'll see it's making a promise to my SearchService 'get' function, and is expecting a result set back of type ISearchResult[]. This is the result we get back from the previous image of my SPSearchService.
The last piece which ties it together is when I am setting this.setState({resulsts:data}); Now, I'm not entirely sure this is the cleanest (or correct?) way to pass a list of my results down to my child React components, so if there is a better way, I'd love to hear it! When the state is set from the promise, the UI will re-bind and populate my document cards. So how does that work?
Well, if you look on line 30 you'll see I have a react component called "InlineSearchResults" which takes a property of results,which is bound to my state object. My InlineSearchResults component is just a basic component that contains a Fabric UI <List> component as shown below.
You'll notice I am binding this._onRenderCell for my list. This will essentially, bind the UI for each SearchResult item returned from the parent component (when I set the state and passed it as parameter to this component). When the List (which is bound to item.props.results) receives it's data, onRenderCell will execute and return a new react component of "InlineSearchItem", which takes an ISearchResult (shown above) object and render it into the List component.
This react component is the document card, which is everything contained in the image below.
If you are just starting out in Office365 development and haven't had a chance to check out Office Fabric, you should. It is extremely easy to use and allows you to build interfaces that fit directly within the current UI of the Office platform suite. You'll notice again that I am importing from Office Fabric at the top of the file, which allows me to use the DocumentCard, DocumentCardActivity and DocumentCardPreview components.
Once I have a reference to these, it's extremely easy to hook them up. Remember in the onCellRender function in the previous component that was passing an object of ISearchResult? Well, I can access this item using this.props.item and grab all the properties to complete my document card. For this webpart, I am only searching documents, so I have harded the icon type to word document. But you will notice that I have already pulling in the file type from the search query and in the future the webpart will dynamically load the icon type for each type of search result returned.
And that's basically it! There are couple modules (interfaces) that I didn't show here, which are the properties for each component. But, now I am ready to go. I can just package up my SPFx webpart and deploy it on the page and have an inline search webpart without having to navigate away from my communication sites landing pages!
I hope you enjoyed this post on SPFx and once I finish building this webpart, I will be providing all of the source code to anyone who is interested in downloading and playing around with it. A big thanks to Waldek , Elio Struyf, Bob German and of course Vesa for leading the way in SPFx development and their contributions to the community.
If you are looking to get into SharePoint Framework development, please checkout the documentation and the github repository to find samples and tutorials.
Share