Lately I was working on a client intranet project. The client wanted a People directory and a possibility to search for people. During some refinement sessions, the demand to show some custom user profile properties in the people directory came up. So using the out of the box modern search result page for people (/_layouts/15/search.aspx/people), was not an option anymore. This page can not be adjusted. So we started to look at the People directory web part in the PnP Starter kit.
Great jump start
Using the PnP Starter kit People directory web part is a great way to jump start building your customisation. It delivers already some great functionalities in the form of an A-Z index, search and a basic list layout showing people using the Office Fabric UI React Persona component. So we advanced the web part with some styling and extra functionality using Office Fabric UI React Callout component in order to show a details card when clicking on a person. This way we were able to show some more specific user details and the custom User profile properties we had added for this customer.

Search issue
When we started to test the People directory web part with real life people in it, we started to see some strange things. When you click on a letter in the A-Z Index on top of the web part, the web part is building a SharePoint Search REST API URL with a query text parameter. This query text looks like this:
const query: string = searchQuery === null ? `LastName:${index}*` : searchQuery.replace(/'/g, `''`)
As you can see the query text will let SharePoint Search API retrieve all people where the LastName starts with the clicked letter from the Index. I highlighted starts with here, because that is what is assumes IMHO. Actually it says: retrieve all people where the LastName contains the clicked letter from the Index. With the wildcard prepended, this will give you results for B* like Beatrix, Braun, etc. BUT, this will also retrieve last names like: Fulham-Braun, Troy Best, or any last name. These names contains B*, but don’t start with B*! That is not what we would expect as an end user when clicking on the letter B in the Index. Well at least not my client.
As pointed out by Mikael Svenson blog, How to do “starts with” in KQL, it is actually not possible using KQL language. The part before the wildcard should be a whole word and the operator should be an equal sign (=) instead of a contains (:). In the case of using the first letter, this won’t work.
Solution
The web part converts the retrieved items from the search API into a javascript object array IPerson[] called people, containing all the necessary properties to be used in the web part. To get this working I solved this by reducing the people IPerson[] array where the first letter is not equal to the clicked Index letter:
if (this.state.searchQuery === '') { // An Index is used to search people. //Reduce the people collection if the first letter of the firstName of the person is not equal to the selected index people = people.reduce((result: IPerson[], person: IPerson) => { if (person.firstName && person.firstName.indexOf(selectedIndex) === 0) { result.push(person); } return result; }, []); }
Reducing the IPerson[] array like this will give you the right results. The removed results will alway come back at other letters in the Index where they actually start with the letter.
Summary
The PnP Starter kit has a lot of nice functionalities, which you can use in your organisation or in your projects. The People directory is a nice web part to search for people with in your organisation. It has a great option to search for people or to use an index. Using this index showed in some cases some rare results, showing people starting with other letters than the clicked letter in the index. Because we are working with a custom solution, we are able to work around this writing some extra code. I haven’t found a direct solution using the Search API itself. If you have any suggestion on this, please leave a comment below.
Sharing is caring!
1 Pingback