How to customize the person hover card in PnP Modern Search

May 28, 2024·
Patrik Hellgren
Patrik Hellgren
· 5 min read

This post was inspired by a question in the PnP Modern Search Github repo on if it was possible to customize the person hover card with custom properties.

To accomplish this you have to enable Microsoft Graph Toolkit for your chosen layout. In this example we will use the details list and customize the Editor column to render as a mgt-person component. When hovering on the component the mgt-person-card will popup and then under additional details we will have our extension property for Customer ID displayed.

This example assumes that we have an extension property registered in Entra ID called extension_e7182bc3462d439f940ec10d277071f6_CustomerID containing the Customer ID that we want to be displayed in the additional properties of the person card for the editor of the listed item. Make sure to replace this with the custom property that you want instead, this could be any user property not just extension properties.

Step-by-step guide

  1. Start by adding the PnP Modern Search search results webpart to your page if it´s not already there.
  2. Configure page 1 of the webpart properties to have your wanted results displayed. For this example to work as expected, make sure that you are returning documents, folders or list items and that EditorOWSUSER is selected under Selected properties.
  3. On page 2 of the webpart properties, select Details List as the layout and then enable Use Microsoft Graph Toolkit.
  4. Now we will add the Editor column to the list so click Manage columns to open the columns editor.
  5. In the column editor, on the empty row under Column display name type Editor. Then check the box under Use Handlebars expression.
  6. Now we will customize the column display so click the edit button next to Column value to open the Handlebars expression editor.
  7. In the Handlebars editor paste the following Handlerbars expression:
{{#if @item.EditorOWSUSER}}
  <style>
      mgt-person {
        --person-line1-font-weight: 400;
        --person-line1-font-size: 14px;
      }
  </style>
  <mgt-person
      person-query="{{getUserEmail @item.EditorOWSUSER}}"
      view="oneline"
      show-presence="true"
      person-card="hover"
  >
    <template data-type="person-card">
      <mgt-person-card inherit-details>
        <template data-type="additional-details">
          <mgt-get resource="/users/\{{ person.id }}?$select=extension_e7182bc3462d439f940ec10d277071f6_CustomerID" version="v1.0">
            <template>
              <div>
                <div data-if="extension_e7182bc3462d439f940ec10d277071f6_CustomerID">
                  <h4>Customer ID:</h4>
                    \{{ extension_e7182bc3462d439f940ec10d277071f6_CustomerID }}
                </div>
              </div>
            </template>
          </mgt-get>
        </template>
      </mgt-person-card>
    </template>
  </mgt-person>
{{/if}}
  1. Click Save in the Handlebars expression editor and then Add and save in the columns editor.
  2. That’s it, we should now see the Editor column displayed with the editors avatar and display name. If we hover on the avatar or name the person card will popup and when clicking the down arrow the additional details for the editor will be displayed and there the Customer ID is now also displayed.

Detailed explanation of the Handlebars expression

So let’s break the Handlebars expression apart to see what it does.

First we check that we have a value in the EditorOWSUSER field so that we don’t have any unforeseen rendering happening:

{{#if @item.EditorOWSUSER}}

Then we render some styling for our mgt-person component:

  <style>
      mgt-person {
        --person-line1-font-weight: 400;
        --person-line1-font-size: 14px;
      }
  </style>

Then we render the mgt-person component and configure the properties so that it is displayed the way we want. The person-query property should contain a value that the user can be found by so I usually use the email address that we can get by using the Handlebars helper getUserEmail and an OWSUSER managed property:

  <mgt-person
      person-query="{{getUserEmail @item.EditorOWSUSER}}"
      view="oneline"
      show-presence="true"
      person-card="hover"
  >

Then we define the person card template for the person component:

    <template data-type="person-card">

In the person card template we will just have the person card component and it should inherit the details:

      <mgt-person-card inherit-details>

Then we define the additional details template for the person card component:

        <template data-type="additional-details">

Then we use the mgt-get component to call Graph and get the users properties that we want to use. In this case we want a specific property from the user that is displayed in the person component so we use the Microsoft Graph Toolkit (MGT) token person for this. Since MGT uses a similar syntax to PnP Modern Search Handlebars for token replacement we need to escape the usage of curly braces so take note of the \ in front of the first curly brace, this is important since we don’t want Handlebars to parse this before sending it on to the MGT templating engine:

          <mgt-get resource="/users/\{{ person.id }}?$select=extension_e7182bc3462d439f940ec10d277071f6_CustomerID" version="v1.0">

Then we define the template to be used by mgt-get to render the additional details. Here we use HTML to design how the information should be rendered. In this case we just have a div containing a header and the value for the Customer ID property. Again note the escaping of the first curly brace to have Handlebars pass this on to MGT. Also note the data-if property which will have MGT check if our custom property contains a value before rendering the contents of the div.

            <template>
              <div>
                <div data-if="extension_e7182bc3462d439f940ec10d277071f6_CustomerID">
                  <h4>Customer ID:</h4>
                    \{{ extension_e7182bc3462d439f940ec10d277071f6_CustomerID }}
                </div>
              </div>
            </template>

So that was it, hopefully you will now have knowledge on how to customize the person card in the PnP Modern Search People layout.

Handling Exchange Server extensionAttributes

A special case that we sometimes want to handle is the use of extension attributes that has been synchronized from Exchange Server on-prem. These are called extensionAttribute1 - extensionAttribute15 in Entra ID and need to be accessed in a different way than the usual user properties. Change the mgt-get section to look like this to display extensionAttribute1:

          <mgt-get resource="/users/\{{ person.id }}/onPremisesExtensionAttributes" version="v1.0">
            <template>
              <div>
                <div data-if="extensionAttribute1">
                  <h4>Customer ID:</h4>
                    \{{ extensionAttribute1 }}
                </div>
              </div>
            </template>
          </mgt-get>
You can use Microsoft Graph Explorer to test the mgt-get resource query and see that it returns what you want.