TransWikia.com

Customizing the PnP people search handlebar template in SharePoint online

SharePoint Asked by GSD - SharePoint on December 13, 2020

I am using the modern PnP SPFx people search web part – and for the people search below is the out of the box template is generated by the web part:

<content id="template">

    <style>
        #pnp-modern-search_{{@root.instanceId}} .personaCard {
            margin: 10px;
        }
    </style>

    <div id="pnp-modern-search_{{@root.instanceId}}" class="template_root">
        {{#if @root.hasPrimaryOrSecondaryResults}} 
            <div class="template_defaultCard">
                {{#if showResultsCount}}
                <div class="template_resultCount">
                    <label class="ms-fontWeight-semibold">{{getCountMessage @root.paging.totalItemsCount keywords}}</label>
                </div>
                {{/if}}
                <div class="ms-Grid">
                    <div class="ms-Grid-row">
                        {{#each items as |item|}}
                        <div class="ms-Grid-col ms-sm12 ms-md12 ms-lg12">
                            {{#> resultTypes item=item}}
                                <div class="personaCard">
                                    {{#with (split AccountName '|')}}
                                        <pnp-persona-card fields-configuration="{{JSONstringify ../../../peopleFields}}" item="{{JSONstringify item}}" persona-size="{{../../../personaSize}}" />
                                    {{/with}}
                                </div>
                            {{/resultTypes}}
                        </div>
                        {{/each}}
                    </div>
                </div>
            </div>
            {{#if @root.paging.showPaging}}
                <pnp-pagination 
                    total-items="{{@root.paging.totalItemsCount}}" 
                    hide-first-last-pages="{{@root.paging.hideFirstLastPages}}"
                    hide-disabled="{{@root.paging.hideDisabled}}"
                    hide-navigation="{{@root.paging.hideNavigation}}"
                    range="{{@root.paging.pagingRange}}" 
                    items-count-per-page="{{@root.paging.itemsCountPerPage}}" 
                    current-page-number="{{@root.paging.currentPageNumber}}"
                >
                </pnp-pagination>
            {{/if}}
        {{else}}
            {{#unless showBlank}}
                <div class="template_noResults">{{@root.strings.NoResultMessage}}</div>
            {{/unless }}
        {{/if}}
    </div>
</content>       
<content id="placeholder">   
    <div id="pnp-modern-search_{{@root.instanceId}}" class="placeholder_root">
        <div class="template_defaultCard">
            {{#if showResultsCount}}
                <div class="template_resultCount">
                    <span class="shimmer line" style="width: 20%"></span>
                </div>
            {{/if}}
            <div class="ms-Grid"> 
                <div class="ms-Grid-row">
                    {{#times @root.paging.totalItemsCount}}
                        <div class="ms-Grid-col ms-sm12 ms-md12 ms-lg12">
                            <pnp-persona-card-shimmers persona-size="{{@root.personaSize}}"></pnp-persona-card-shimmers>
                        </div>
                    {{/times}}
                </div>
            </div>
        </div>
    </div>
</content>

As I understand the below line is displaying the people search related data:

<pnp-persona-card fields-configuration="{{JSONstringify ../../../peopleFields}}" item="{{JSONstringify item}}" persona-size="{{../../../personaSize}}" />

The above code is giving very limited result with just user full name and email:

People Search Template Result

My question is – how can we add additional user properties to the above template like – Department, UserPhone, CellPhone, Manager, AboutMe, HomePhone, Office, etc. ?

The above property I could able to configure through the manage property configuration pane – however, my intention here is to handle this through the handlebar customization because I have some scenarios, where I need to display the value conditionally, so, if someone can add a sample if condition with some values like – HomePhone, Office, etc, to this exiting handlebar template would be a great help.

3 Answers

If you want to apply more conditions in the template, you use Handlebars. Basically you use the managed properties values inside curly braces: {{}} inside the template.

Example 1:

  {{#unless WorkEmail}} 
     <p>if there is no work email, render this</p>
  {{/unless}}

In this example, if there's no work email, render the paragraph. This is handlebars way of having "If null" or !

Example 2

  {{#if WorkEmail}} 
      <p>This paragraph will render only if the managed property has a truthy value</p>
  {{/if}}

This example uses if condition.

Note in these examples am just using the WorkEmail managed property, but you can choose other managed properties the same way. The web part uses handlebars built it helpers (the if and unless). If you want to create your own helpers for example to check if the managed property equals a specific value (not just true/false checks), then it's not supported by this version of the modern search webparts and you'll need to upgrade to the newer one to have custom helpers (which isn't free): https://www.aequos.ca/features

Correct answer by Mohamed Derhalli on December 13, 2020

Okay lets say you would have a card style layout go to your search webpart settings - on page 2 of the settings enter following values into Selected Properties

Title,Path,Created,Filename,SiteLogo,PreviewUrl,PictureThumbnailURL,ServerRedirectedPreviewURL,ServerRedirectedURL,HitHighlightedSummary,FileType,contentclass,ServerRedirectedEmbedURL,DefaultEncodingURL,owstaxidmetadataalltagsinfo,Author,AuthorOWSUSER,SPSiteUrl,SiteTitle,IsContainer,IsListItem,HtmlFileType,SiteId,WebId,UniqueID,NormSiteID,NormListID,NormUniqueID,Rank,AccountName,FirstName,LastName,Department,WorkPhone,WorkEmail,PictureURL,SOSDescription,EndDateOWSDATE,EventDateOWSDATE,ContentSource,JobTitle,Location,EditorOWSUSER,ModifiedBy,Description,ModifiedOWSDATE,ContentType,OriginalPath,FileExtension,ParentLink,PromotedState,PromotedStateOWSNMBR,IsDocument,NormWebID

On page 3 of the search webpart settings select the "Results layout"

Custom

Then edit the template and put following template for card layout into the editor box

    <content id="template">

    <style>
    /* Insert your CSS overrides here */
    #pnp-modern-search_{{@root.instanceId}} {
    /* Insert your CSS overrides here */
    }
    
    .livepersona-themePrimary a {
        color: {{ @root.themeVariant.palette.themePrimary }};
    }           

    .livepersona-card-item, 
    .template_livepersona-card {
        margin-right: 15px;
        -webkit-box-flex: 0;
        -ms-flex: 0 0 345px;
        flex: 0 0 345px;
    }
    .livepersona-info {
        color: {{@root.themeVariant.palette.neutralPrimary}};
    }
    .live-persona-card {
        background-color: {{@root.themeVariant.palette.white}}; 
        border: 1px solid {{@root.themeVariant.palette.neutralLight}};
        box-sizing: border-box;
        max-width: 320px;
        min-width: 206px;
        position: relative;
        margin-bottom: 15px;
        user-select: none;
    }
    .live-persona-card:hover {
        cursor: pointer;
        border-color: {{@root.themeVariant.palette.neutralTertiaryAlt}} !important;
    }
    .livepersona-card-headercontainer {
        border-bottom: 1px solid {{@root.themeVariant.palette.neutralLight}};
        position: relative;
        background-color: {{@root.themeVariant.palette.white}};
        overflow: hidden;
    }
    [dir="ltr"] .livepersona-ContainerCard-title {
        text-align: left;
    }
    .livepersona-ContainerCard-title {
        font-size: 17px;
        font-weight: 300;
        font-weight: 400;
        width: 100%;
        line-height: 17px;
        margin-top: 30px;
        padding: 0 12px;
        color: {{@root.themeVariant.palette.themePrimary}};       
        -webkit-animation-name: ms-fadeIn;
        animation-name: ms-fadeIn;
        -webkit-animation-duration: 267ms;
        animation-duration: 267ms;
        -webkit-animation-timing-function: cubic-bezier(.1,.9,.2,1);
        animation-timing-function: cubic-bezier(.1,.9,.2,1);
        -webkit-animation-delay: 50ms;
        animation-delay: 50ms;
        -webkit-box-sizing: border-box;
        box-sizing: border-box;
    }
    .livepersona-ContainerCard-subTitle {
        padding: 0px 12px;
        font-size: 14px;
        font-weight: 400;
        padding-top: 5px;
        color: {{@root.themeVariant.palette.neutralPrimary}};
        -webkit-animation-name: ms-fadeIn;
        animation-name: ms-fadeIn;
        -webkit-animation-duration: 167ms;
        animation-duration: 167ms;
        -webkit-animation-timing-function: cubic-bezier(.1,.9,.2,1);
        animation-timing-function: cubic-bezier(.1,.9,.2,1);
        -webkit-animation-delay: .25s;
        animation-delay: .25s;
    }
    .livepersona-ContainerCard-subTitle strong, .livepersona-ContainerCard-subTitle b
    {
        color: {{@root.themeVariant.palette.themePrimary}};
    }
    .livepersona-card-header-normal {
        border-bottom: 2px solid {{@root.themeVariant.palette.neutralLight}};
    }
    .livepersona-card-header-normal {
        position: relative;
        width: 100%;
        padding-top: 0px;
        height: auto;
        cursor: pointer;
        background-color: {{@root.themeVariant.palette.white}};
        display: block;
    }
    .livepersona-card-titletopfix {
        margin-top: 10px;
    }
    .livepersona-margin-10px {
        margin: 10px
    }
    .livepersona-image {
        font-family: "Segoe UI", "Segoe UI Web (West European)", "Segoe UI", -apple-system, BlinkMacSystemFont, "Roboto", "Helvetica Neue", sans-serif;
        font-size: 14px;
        font-weight: 400;
        overflow: hidden;
        animation-duration: 0.367s;
        animation-timing-function: cubic-bezier(0.1, 0.25, 0.75, 0.9);
        margin-right: 10px;
        top: 0px;
        left: 0px;
        width: 100px;
        height: 100px;
        border: 0px none;
        border-radius: 50%;
        perspective: 1px;
    }

    .livepersona-image img {
        display: block;
        opacity: 1;
        width: 100%;
        height: 100%;
        object-fit: cover;
        position: absolute;
        left: 50%;
        top: 50%;
        transform: translate(-50%, -50%);
    }

    .livepersona-flex-container {
        display: -ms-flexbox;
        display: -webkit-flex;
        display: flex;
        -webkit-flex-direction: row;
        -ms-flex-direction: row;
        flex-direction: row;
        -webkit-flex-wrap: nowrap;
        -ms-flex-wrap: nowrap;
        flex-wrap: nowrap;
        -webkit-justify-content: flex-start;
        -ms-flex-pack: start;
        justify-content: flex-start;
        -webkit-align-content: stretch;
        -ms-flex-line-pack: stretch;
        align-content: stretch;
        -webkit-align-items: flex-start;
        -ms-flex-align: start;
        align-items: flex-start;
    }

    .livepersona-flex-item:nth-child(1) {
        -webkit-order: 0;
        -ms-flex-order: 0;
        order: 0;
        -webkit-flex: 0 1 auto;
        -ms-flex: 0 1 auto;
        flex: 0 1 auto;
        -webkit-align-self: stretch;
        -ms-flex-item-align: stretch;
        align-self: stretch;
    }

    .livepersona-flex-item:nth-child(2) {
        -webkit-order: 0;
        -ms-flex-order: 0;
        order: 0;
        -webkit-flex: 1 1 auto;
        -ms-flex: 1 1 auto;
        flex: 1 1 auto;
        -webkit-align-self: stretch;
        -ms-flex-item-align: stretch;
        align-self: stretch;
    }

    .livepersona-primaryText {
        white-space: nowrap;
        color: {{ @root.themeVariant.palette.neutralPrimary }};
        font-weight: 300;
        font-size: 21px;
    }
    </style>




    <div class="template_root">
        {{#if @root.hasPrimaryOrSecondaryResults}} 
            <div class="template_defaultCard">
                {{#if showResultsCount}}
                <div class="template_resultCount">
                    <label class="ms-fontWeight-semibold">{{getCountMessage @root.paging.totalItemsCount keywords}}</label>
                </div>
                {{/if}}
                <div class="document-card-container">
                    {{#each items as |item|}}
                    <div class="document-card-item">
                        {{#> resultTypes item=item}}
                            {{!-- The block below will be used as default item template if no result types matched --}}
                            {{#eq item.contentclass 'STS_ListItem_851'}}
                                <pnp-video-card data-item="{{JSONstringify item}}" data-fields-configuration="{{JSONstringify @root.documentCardFields}}" data-enable-preview="{{@root.enablePreview}}" data-show-file-icon="{{@root.showFileIcon}}" data-is-compact="{{@root.isCompact}}"></pnp-video-card>
                            {{else}}
                                <pnp-document-card data-item="{{JSONstringify item}}" data-fields-configuration="{{JSONstringify @root.documentCardFields}}" data-enable-preview="{{@root.enablePreview}}" data-show-file-icon="{{@root.showFileIcon}}" data-is-compact="{{@root.isCompact}}"></pnp-document-card>
                            {{/eq}} 
                        {{/resultTypes}}
                    </div>
                    {{/each}}
                </div>
            </div>
            {{#if @root.paging.showPaging}}
                <pnp-pagination 
                    data-total-items="{{@root.paging.totalItemsCount}}" 
                    data-hide-first-last-pages="{{@root.paging.hideFirstLastPages}}"
                    data-hide-disabled="{{@root.paging.hideDisabled}}"
                    data-hide-navigation="{{@root.paging.hideNavigation}}"
                    data-range="{{@root.paging.pagingRange}}" 
                    data-items-count-per-page="{{@root.paging.itemsCountPerPage}}" 
                    data-current-page-number="{{@root.paging.currentPageNumber}}"
                >
                </pnp-pagination>
            {{/if}}
        {{else}}
            {{#unless showBlank}}
                <div class="template_noResults">{{@root.strings.NoResultMessage}}</div>
            {{/unless}}
        {{/if}}
    </div>
</content>

<content id="placeholder">   
    <div class="placeholder_root">
        <div class="template_defaultCard">
            {{#if showResultsCount}}
                <div class="template_resultCount">
                    <span class="shimmer line" style="width: 20%"></span>
                </div>
            {{/if}}
            <div class="document-card-container"> 
                {{#times @root.paging.totalItemsCount}}
                    <div class="document-card-item">
                        <pnp-document-card-shimmers data-is-compact="{{@root.isCompact}}"></pnp-document-card-shimmers>
                    </div>
                {{/times}}
            </div>
        </div>
    </div>
</content>

then configure the "Result Types" by clicking on the "Edit Result Types" button Add a new row and enter following values

Managed Property = contentclass
Operator = Contains
Condition Value = SPSPeople

And in the "Inline template" editor box enter following code

    <div class="template_livepersona-card">

    <div class="livepersona-card-item">

        <div>
            <div tabindex="0" data-is-focusable="true" role="button"
                class="ms-DocumentCard ms-DocumentCard--actionable live-persona-card">

                {{#with (split AccountName '|')}}
                <div style="position: relative; height: 100%;">

                    <div aria-label="{{../FirstName}} {{../LastName}}" class="livepersona-card-header-normal"
                        data-focusable-context="ActivityCards" data-is-focusable="true" data-interception="propagate"
                        data-nested-context="Card" data-sp-sitetype-hint="Comm" 
                        title="{{../FirstName}} {{../LastName}}" tabindex="-1">

                        <div title="{{../FirstName}} {{../LastName}}">

                        <div class="ms-DocumentCardPreview livepersona-card-headercontainer">
                            <div class="livepersona-flex-container">
                                <div class="livepersona-flex-item ms-Persona-coin ms-Persona--size100">
                                    <div class="ms-Persona-imageArea">
                                        <div class="ms-Image ms-Persona-image livepersona-image livepersona-margin-10px" style="width: 100px; height: 100px;">
                                            <pnp-live-persona data-upn="{{[2]}}" data-disableHover="false" data-template="<img class='img-preview ms-Image-image is-loaded ms-Image-image--cover ms-Image-image--landscape is-fadeIn' src='/_layouts/15/userphoto.aspx?size=L&username={{[2]}}'' alt=''/>" />
                                        </div>
                                    </div>
                                </div>
                                <div class="livepersona-flex-item">
                                    <div class="livepersona-primaryText livepersona-themePrimary livepersona-margin-10px">
                                        <a target="_blank" data-interception="off" 
                                            href="https://delve.office.com/?q={{../FirstName}}+{{../LastName}}&searchpage=1&searchview=people&v=search"
                                            >
                                            <pnp-live-persona data-upn="{{[2]}}" data-disableHover="false" data-template="{{../FirstName}} {{../LastName}}" />
                                            </a>
                                            
                                    </div>
                                    <a target="_blank" data-interception="off"  class="livepersona-info"
                                        href="https://delve.office.com/?q={{../FirstName}}+{{../LastName}}&searchpage=1&searchview=people&v=search"
                                        >
                                    <span>
                                    <pnp-live-persona data-upn="{{[2]}}" data-disableHover="false" data-template="
                                        {{#if ../JobTitle}}
                                            <span>
                                                <i class='ms-Icon ms-Icon--Work' aria-hidden='true'></i> {{../JobTitle}}<br />
                                            </span>
                                        {{/if}}
                                        {{#if ../Department}}
                                            <span>
                                                <i class='ms-Icon ms-Icon--Group' aria-hidden='true'></i> {{../Department}}<br />
                                            </span>
                                        {{/if}}" />
                                    </span>
                                    </a>
                                </div>
                            </div>
                        </div>

                            <a aria-label="{{../FirstName}} {{../LastName}}" 
                            data-focusable-context="ActivityCards" data-is-focusable="true"
                            data-nested-context="Card" data-sp-sitetype-hint="Comm" href="{{getUrl item}}"
                            target="_blank" data-interception="off" title="{{../FirstName}} {{../LastName}}" tabindex="-1">
                                <div class="livepersona-ContainerCard-title livepersona-card-titletopfix  ">
                                
                                </div>
                                <div class="livepersona-ContainerCard-subTitle livepersona-themePrimary">
                                        {{#if ../WorkPhone}}
                                            <span class="persona-link ">
                                                <a href="tel:{{replace (replace (replace ../WorkPhone "-" "") "/" "") " " ""}}" title="Telephone">
                                                    <i class="ms-Icon ms-Icon--Phone" aria-hidden="true"></i>&nbsp;
                                                    {{../WorkPhone}}
                                                </a><br />
                                            </span>
                                        {{/if}}
                                        {{#if ../WorkEmail}}
                                            <span class="persona-link ">
                                                <a href="mailto:{{../WorkEmail}}" title="Email">
                                                    <i class="ms-Icon ms-Icon--Mail" aria-hidden="true"></i>&nbsp;
                                                    {{../WorkEmail}}
                                                </a>
                                            </span><br />
                                        {{/if}}
                                            <span class="persona-link ">
                                                <a target="_blank" data-interception="off" href="https://delve.office.com/?q={{../FirstName}}+{{../LastName}}&searchpage=1&searchview=people&v=search" title="Delve">
                                                    <i class="ms-Icon ms-Icon--DelveLogo" aria-hidden="true"></i>&nbsp;
                                                    Find this person in Delve
                                                </a>
                                            </span>
                                </div>
                            </a>
                        </div>
                    </div>
                </div>
                
                {{/with}}
            </div>
        </div>
    </div>           
</div>

That should render some nice persona cards (maybe needs some CSS styling) and when hovering with the mouse over a person the live persona card shows up.

Answered by Georg Trixl on December 13, 2020

You have these options out of the box from the property pane itself. enter image description here

enter image description here

Answered by Harsha Vardhini on December 13, 2020

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP