Autocomplete Dropdown With ListItem Picker Of PnP Controls In SPFx Webpart

In this article, we will learn how to implement autocomplete dropdown with Listitem Picker controls of PnP in SPFx webpart

Background

 
With the recent popularity of SPFx, developers are required to develop some complex requirements using the SharePoint framework web part. Many of these requirements are common and need to be developed again and again. Microsoft has provided Office UI fabric react based controls which can be easily used in our SPFx web part. Still, there are some controls that are missing in Office UI fabric, thanks to our awesome PnP initiative, the community has stepped forward and developed many more controls that can be used in our SPFx solutions.
 
You can know and read about all the controls available from PnP controls library at this link. Today we will learn about Listitem picker control of PnP and how it can be utilized in SPFx webpart.
 

Scenario

 
Suppose you are developing a SPFx webpart custom form to get data from the user. Many times, we would need to bind lookup columns (master data) in the dropdown to allow users to select. Traditionally what we would do is create a dropdown control and bind its options by querying master list (one of the columns would be bound as key and another as a display value). In such cases, we can use PnP ListItemPicker control which does the heavy lifting of binding values to control by calling rest api internally and binding the id and value column as per our configuration. Let us see how to do it.
 
Let's get started and create web part.
 

Step - Create SPFx solution and webpart

 
Run below commands in sequence.
 
Open a node js command prompt and create a directory for SPFx solution.
  1. md PnPControlsDemo    
  2. cd PnPControlsDemo   
Let us now create SPFx solution and add web part to it.
  1. yo @microsoft/sharepoint  
Please select below options, please note we need to choose React framework as this control is based on react.
 
Autocomplete Dropdown With ListItem Picker Of PnP Controls In SPFx Webpart
 
Once you select all options in wizard one by one, it will take some time to generate the code structure.
 
Autocomplete Dropdown With ListItem Picker Of PnP Controls In SPFx Webpart
 
Now let us install required npm packages to use PnP controls. run below command.
  1. npm install @pnp/spfx-controls-react --save   
After it is completed, open same folder in Visual Studio code( you can use any other editor also).
 
Now let us modify code to use these controls.
 

Step - Passing WebPart context to React components 

 
ListItem Picker control requires Sharepoint site context to work with, hence we will pass it from our web part file to react components.
 
Open src\webparts\controls\components\IControlsProps.ts
 
Modify code to below,
  1. import { WebPartContext } from '@microsoft/sp-webpart-base';        
  2. export interface IControlsProps {      
  3.   description: string;      
  4.   context: WebPartContext;        
  5. }    
Open src\webparts\controls\ControlsWebPart.ts
 
Modify render method to pass context.
  1. public render(): void {    
  2.    const element: React.ReactElement<IControlsProps > = React.createElement(    
  3.      Controls,    
  4.      {    
  5.        description: this.properties.description,    
  6.        context:this.context    
  7.      }    
  8.    );    
  9.    ReactDom.render(element, this.domElement);    
Please note we have just added line 'context:this.context' .
 

Step - Modify the React component associated with webpart

 
Open src\webparts\controls\components\Controls.tsx
 
Import list item picker control and a button from office-ui-fabric-react
  1. import { ListItemPicker } from '@pnp/spfx-controls-react/lib/listItemPicker';  
  2. import {  PrimaryButton } from 'office-ui-fabric-react';  
Create Interface to Store State, add below code below last import statement,
  1. export interface IControlsState {    
  2.   selectedValues:any[];  
  3. }   
Modify component as below,
  1. export default class Controls extends React.Component<IControlsProps, IControlsState> {    
  2.     
  3.   constructor(props: IControlsProps, state: IControlsState) {        
  4.     super(props);        
  5.     this.state = {selectedValues:[]};        
  6.   }     
  7.     
  8. .......    
Modify the render method, refer below code and modify as per your requirement, 
  1. public render(): React.ReactElement<IControlsProps> {  
  2.     return (  
  3.       <div className={ styles.controls }>  
  4.         <div className={ styles.container }>  
  5.           <div className={ styles.row }>  
  6.             <div className={ styles.column }>  
  7.               <span className={ styles.title }>Welcome to SharePoint!</span>  
  8.               <p className={ styles.subTitle }>Customize SharePoint experiences using Web Parts.</p>  
  9.               <p className={ styles.description }>{escape(this.props.description)}</p>  
  10.               <a href="https://aka.ms/spfx" className={ styles.button }>  
  11.                 <span className={ styles.label }>Learn more</span>  
  12.               </a>  
  13.             </div>  
  14.           </div>  
  15.         </div>  
  16.         <br></br>  
  17.         Select Asset  
  18.         <ListItemPicker listId='ba682bc2-351e-45ae-8cbe-b0512ba0291a'  
  19.                 columnInternalName='Title'  
  20.               keyColumnInternalName='Id'  
  21.                 itemLimit={2}  
  22.                 onSelectedItem={this.onSelectedItem}  
  23.                 context={this.props.context}   
  24.                 suggestionsHeaderText = "Please select asset"  
  25.                 />  
  26.                 <br></br>  
  27.         <PrimaryButton text="Submit" onClick={this.submitClicked}  />  
  28.   
  29.       </div>  
  30.     );  
  31.   }  
Now let us see, what different attribute means in the below code,
  • ListId - GUID of list from which we need to display values in control.
  • ColumnInternalName - Internal name of column which you need to display.
  • KeyColumnInternamName - Internal name of column which you wanted to use as key, in most case this will be ID column.
  • itemLimit - this is a maximum number of item we want user to select. If you need single-valued, set this to 1. 
Others are pretty self explanatory
 
Now let us add a method to set state when user will select values in control.
 
Here we are overriding state variable as soon as selected or changed in control.
  1.  private onSelectedItem = (data: { key: string; name: string }[]) :void=>{  
  2.     this.setState({selectedValues:data});  
  3. }  
Now let us write event which handle submit button click and display selected values in alert box by reading from state. 
  1. private submitClicked = ():void => {  
  2.     alert(JSON.stringify(this.state.selectedValues))   ;  
  3.   }  
Please note that, I am using below List as master data to display values in control.
Autocomplete Dropdown With ListItem Picker Of PnP Controls In SPFx Webpart
We are done with code, now let us run it. Use gulp serve command in node js command prompt. Please note that this control requires the context of SharePoint site because it has to display list items from SharePoint list. So we will test this webpart in SharePoint workbench.
 
Once local workbench is opened in the browser, open SharePoint workbench.
 
https://amazonprime.sharepoint.com/sites/war/_layouts/15/workbench.aspx
 
Below is the output of web part.
 
Autocomplete Dropdown With ListItem Picker Of PnP Controls In SPFx Webpart
Start typing in Select asset control.
 
Autocomplete Dropdown With ListItem Picker Of PnP Controls In SPFx Webpart
Once you select one or more values and click on submit we can see the selected values are displayed in alert.
 
Autocomplete Dropdown With ListItem Picker Of PnP Controls In SPFx Webpart

Conclusion

 
This control can be very useful as we don't have to write repetitive code to display master data in dropdown and added advantage is that it provide auto-complete feature. Use this reduce your development time :)
 
Thanks for reading, hope this helps..Happy coding..!!