PnP People Picker Control In SharePoint Framework

PnP React Controls

 
Patterns and Practices (PnP) provides a list of reusable React controls to developers for building solutions such as webparts and extensions using SharePoint Framework.
 
Refer to this link to get the list of React controls for SPFx.
 
You will see how to use the PnP People Picker control in SPFx webpart.
 

PnP People Picker Control

 
This control renders a People Picker field which can be used to select one or more users from a SharePoint group or site. The control can be configured as mandatory. It will show a custom error message if the field is empty. Refer to this link for more details.
 
PnP People Picker Control In SharePoint Framework
 
PnP People Picker Control In SharePoint Framework
 
I have created a simple custom list which contains the following fields.
 
PnP People Picker Control In SharePoint Framework
 
Person or group Field settings
 
PnP People Picker Control In SharePoint Framework
  • Field Display Name: ProjectMembers
  • Field Internal Name: ProjectMembers
Note
When you are setting the value using PnP js the field name should be <fieldInternalName>Id. Example - ProjectMembersId
 
In this article, you will see how to perform the following tasks,
  • Prerequisites
  • Create SPFx solution
  • Implement People Picker Control solution
  • Deploy the solution
  • Test the webpart
Prerequisites

Create SPFx solution

 
Open Node.js command prompt.
 
Create a new folder.
 
>md spfx-pnpreact-peoplepicker
 
Navigate to the folder.
 
> cd spfx-pnpreact-peoplepicker
 
Execute the following command to create SPFx webpart.
 
>yo @microsoft/sharepoint
 
Enter all the required details to create a new solution. Yeoman generator will perform the scaffolding process and once it is completed, lock down the version of project dependencies by executing the following command.
 
>npm shrinkwrap
 
Execute the following command to open the solution in the code editor.
 
>code .
 

Implement People Picker Control solution

 
Execute the following command to install the PnP React Controls NPM package.
 
>npm install @pnp/spfx-controls-react –save
 
Execute the following command to install the pnp sp library.
 
>npm install @pnp/sp –save
 
Create a new ts file named as “IPeoplepickercontrolState.ts” under Components folder (src\webparts\peoplepickercontrol\components\IPeoplepickercontrolState.ts) and update the code as shown below.
  1. import { MessageBarType } from 'office-ui-fabric-react';  
  2.   
  3. export interface IPeoplepickercontrolState {  
  4.     title: string;  
  5.     users: number[];  
  6.     showMessageBar: boolean;  
  7.     messageType?: MessageBarType;  
  8.     message?: string;  
  9. }  
Open the props file (src\webparts\peoplepickercontrol\components\IPeoplepickercontrolProps.ts) and update the code as shown below.
  1. import { WebPartContext } from "@microsoft/sp-webpart-base";  
  2.   
  3. export interface IPeoplepickercontrolProps {  
  4.   description: string;  
  5.   context: WebPartContext;  
  6. }  
Open the webpart file “src\webparts\datetimepickercontrol\DatetimepickercontrolWebPart.ts” and update the render method.
  1. public render(): void {  
  2.  const element: React.ReactElement<IPeoplepickercontrolProps> = React.createElement(  
  3.    Peoplepickercontrol,  
  4.    {  
  5.      description: this.properties.description,  
  6.      context: this.context  
  7.    }  
  8.  );  
  9.   
  10.  ReactDom.render(element, this.domElement);  
Open the component file “src\webparts\peoplepickercontrol\components\Peoplepickercontrol.tsx” and import the following modules.
  1. import { IPeoplepickercontrolState } from './IPeoplepickercontrolState';  
  2. import { IButtonProps, DefaultButton } from 'office-ui-fabric-react/lib/Button';  
  3. import { TextField } from 'office-ui-fabric-react/lib/TextField';  
  4. import { autobind } from 'office-ui-fabric-react';  
  5. import { MessageBar, MessageBarType, IStackProps, Stack } from 'office-ui-fabric-react';  
  6. import { PeoplePicker, PrincipalType } from "@pnp/spfx-controls-react/lib/PeoplePicker";  
  7. import { sp } from "@pnp/sp";  
  8. import "@pnp/sp/webs";  
  9. import "@pnp/sp/lists";  
  10. import "@pnp/sp/items";  
Update the render method as shown below.
  1.  public render(): React.ReactElement<IPeoplepickercontrolProps> {  
  2.   return (  
  3.     <div className={styles.peoplepickercontrol}>  
  4.       {  
  5.         this.state.showMessageBar  
  6.           ?  
  7.           <div className="form-group">  
  8.             <Stack {...verticalStackProps}>  
  9.               <MessageBar messageBarType={this.state.messageType}>{this.state.message}</MessageBar>  
  10.             </Stack>  
  11.           </div>  
  12.           :  
  13.           null  
  14.       }  
  15.       <TextField label="Title" required onChanged={this._onchangedTitle} />  
  16.       <PeoplePicker  
  17.         context={this.props.context}  
  18.         titleText="Project Members"  
  19.         personSelectionLimit={3}  
  20.         showtooltip={true}  
  21.         isRequired={true}  
  22.         disabled={false}  
  23.         selectedItems={this._getPeoplePickerItems}  
  24.         showHiddenInUI={false}  
  25.         ensureUser={true}  
  26.         principalTypes={[PrincipalType.User]}  
  27.         resolveDelay={1000} />  
  28.       <DefaultButton text="Submit" onClick={this._createItem} />  
  29.     </div>  
  30.   );  
  31. }  
Note
Make sure in the people picker control ensureUser is set to true or else you will not be able to set the values. When ensure user property is true, it will return the local user ID on the current site when doing a tenant wide search.
 
Create the constructor in the component file.
  1. constructor(props: IPeoplepickercontrolProps, state: IPeoplepickercontrolState) {  
  2.    super(props);  
  3.    sp.setup({  
  4.      spfxContext: this.props.context  
  5.    });  
  6.   
  7.    this.state = {  
  8.      title: '',  
  9.      users: [],  
  10.      showMessageBar: false  
  11.    };  
  12.  }  
Create the helper methods in the component file.
  1. constructor(props: IPeoplepickercontrolProps, state: IPeoplepickercontrolState) {  
  2.    super(props);  
  3.    sp.setup({  
  4.      spfxContext: this.props.context  
  5.    });  
  6.   
  7.    this.state = {  
  8.      title: '',  
  9.      users: [],  
  10.      showMessageBar: false  
  11.    };  
  12.  }  
  13.   
  14. reate the helper methods in the component file.  
  15. @autobind  
  16.  private _getPeoplePickerItems(items: any[]) {  
  17.    let getSelectedUsers = [];  
  18.    for (let item in items) {  
  19.      getSelectedUsers.push(items[item].id);  
  20.    }  
  21.    this.setState({ users: getSelectedUsers });  
  22.  }  
  23.   
  24.  @autobind  
  25.  private _onchangedTitle(title: string) {  
  26.    this.setState({ title: title });  
  27.  }  
  28.   
  29.  @autobind  
  30.  private async _createItem() {  
  31.    try {  
  32.      await sp.web.lists.getByTitle("Project Details").items.add({  
  33.        Title: this.state.title,  
  34.        ProjectMembersId: { results: this.state.users }  
  35.   
  36.      });  
  37.   
  38.      this.setState({  
  39.        message: "Item: " + this.state.title + " - created successfully!",  
  40.        showMessageBar: true,  
  41.        messageType: MessageBarType.success  
  42.      });  
  43.   
  44.    }  
  45.    catch (error) {  
  46.      this.setState({  
  47.        message: "Item " + this.state.title + " creation failed with error: " + error,  
  48.        showMessageBar: true,  
  49.        messageType: MessageBarType.error  
  50.      });  
  51.    }  
  52.  }  
Update React component (src\webparts\peoplepickercontrol\components\Peoplepickercontrol.tsx),
  1. import * as React from 'react';  
  2. import styles from './Peoplepickercontrol.module.scss';  
  3. import { escape } from '@microsoft/sp-lodash-subset';  
  4. import { IPeoplepickercontrolProps } from './IPeoplepickercontrolProps';  
  5. import { IPeoplepickercontrolState } from './IPeoplepickercontrolState';  
  6. import { IButtonProps, DefaultButton } from 'office-ui-fabric-react/lib/Button';  
  7. import { TextField } from 'office-ui-fabric-react/lib/TextField';  
  8. import { autobind } from 'office-ui-fabric-react';  
  9. import { MessageBar, MessageBarType, IStackProps, Stack } from 'office-ui-fabric-react';  
  10. import { PeoplePicker, PrincipalType } from "@pnp/spfx-controls-react/lib/PeoplePicker";  
  11. import { sp } from "@pnp/sp";  
  12. import "@pnp/sp/webs";  
  13. import "@pnp/sp/lists";  
  14. import "@pnp/sp/items";  
  15.   
  16. const verticalStackProps: IStackProps = {  
  17.   styles: { root: { overflow: 'hidden', width: '100%' } },  
  18.   tokens: { childrenGap: 20 }  
  19. };  
  20.   
  21. export default class Peoplepickercontrol extends React.Component<IPeoplepickercontrolProps, IPeoplepickercontrolState> {  
  22.   constructor(props: IPeoplepickercontrolProps, state: IPeoplepickercontrolState) {  
  23.     super(props);  
  24.     sp.setup({  
  25.       spfxContext: this.props.context  
  26.     });  
  27.   
  28.     this.state = {  
  29.       title: '',  
  30.       users: [],  
  31.       showMessageBar: false  
  32.     };  
  33.   }  
  34.   public render(): React.ReactElement<IPeoplepickercontrolProps> {  
  35.     return (  
  36.       <div className={styles.peoplepickercontrol}>  
  37.         {  
  38.           this.state.showMessageBar  
  39.             ?  
  40.             <div className="form-group">  
  41.               <Stack {...verticalStackProps}>  
  42.                 <MessageBar messageBarType={this.state.messageType}>{this.state.message}</MessageBar>  
  43.               </Stack>  
  44.             </div>  
  45.             :  
  46.             null  
  47.         }  
  48.         <TextField label="Title" required onChanged={this._onchangedTitle} />  
  49.         <PeoplePicker  
  50.           context={this.props.context}  
  51.           titleText="Project Members"  
  52.           personSelectionLimit={3}  
  53.           showtooltip={true}  
  54.           isRequired={true}  
  55.           disabled={false}  
  56.           selectedItems={this._getPeoplePickerItems}  
  57.           showHiddenInUI={false}  
  58.           ensureUser={true}  
  59.           principalTypes={[PrincipalType.User]}  
  60.           resolveDelay={1000} />  
  61.         <DefaultButton text="Submit" onClick={this._createItem} />  
  62.       </div>  
  63.     );  
  64.   }  
  65.   
  66.   @autobind  
  67.   private _getPeoplePickerItems(items: any[]) {  
  68.     let getSelectedUsers = [];  
  69.     for (let item in items) {  
  70.       getSelectedUsers.push(items[item].id);  
  71.     }  
  72.     this.setState({ users: getSelectedUsers });  
  73.   }  
  74.   
  75.   @autobind  
  76.   private _onchangedTitle(title: string) {  
  77.     this.setState({ title: title });  
  78.   }  
  79.   
  80.   @autobind  
  81.   private async _createItem() {  
  82.     try {  
  83.       await sp.web.lists.getByTitle("Project Details").items.add({  
  84.         Title: this.state.title,  
  85.         ProjectMembersId: { results: this.state.users }  
  86.   
  87.       });  
  88.   
  89.       this.setState({  
  90.         message: "Item: " + this.state.title + " - created successfully!",  
  91.         showMessageBar: true,  
  92.         messageType: MessageBarType.success  
  93.       });  
  94.   
  95.     }  
  96.     catch (error) {  
  97.       this.setState({  
  98.         message: "Item " + this.state.title + " creation failed with error: " + error,  
  99.         showMessageBar: true,  
  100.         messageType: MessageBarType.error  
  101.       });  
  102.     }  
  103.   }  
  104. }    

Deploy the solution

 
Execute the following commands to bundle and package the solution.
 
>gulp bundle --ship
>gulp package-solution --ship
 
Navigate to tenant app catalog – Example - https://c986.sharepoint.com/sites/appcatalog/SitePages/Home.aspx
 
Go to Apps for SharePoint library and upload the package file (sharepoint\solution\spfx-pnpreact-peoplepicker.sppkg). Click Deploy.
 
PnP People Picker Control In SharePoint Framework
 
Test the webpart
 
Navigate to the SharePoint site and add the app.
 
PnP People Picker Control In SharePoint Framework
 
Result
 
Navigate to the page and add the webpart. Enter all the details and click submit, a new item gets created in the SharePoint list.
 
PnP People Picker Control In SharePoint Framework
 
PnP People Picker Control In SharePoint Framework
 

Summary

 
Thus, in this article, you saw how to use PnP People Picker Control in SharePoint Framework.