How To Use Pivot Control Of Fluent UI In SPFx

Introduction

 
The Pivot control and related tabs pattern are used for navigating frequently accessed, distinct content categories. Pivots allow for navigation between two or more content views and rely on text headers to articulate the different sections of content.
 
Tapping on a pivot item header navigates to that header's section content.
 
Tabs are a visual variant of Pivot that uses a combination of icons and text or just icons to articulate section content.
 
 
So, in this article, we will see how to implement pivot control with spfx webpart.
 

Scenario

 
In this example, we will show users and groups of a selected site in a tabbing form. For this, we will use pnpjs to get current site users and site groups and render it in pivot/tabs. We will add a site picker property in webpart property pane configuration so a user can see the output of any sites.
 
At the end, our output will be like this,
 
Output - Pivot
 

Implementation 

  • Open a command prompt
  • Move to the path where you want to create a project
  • Create a project directory using:
  1. md spfx-fluentui-pivot  
Move to the above-created directory using:
  1. cd spfx-fluentui-pivot  
Now execute the below command to create an SPFx solution:
  1. yo @microsoft/sharepoint  
It will ask some questions, as shown below,
 
Project Setup
 
After a successful installation, we can open a project in any source code tool. Here, I am using the VS code, so I will execute the command:
  1. code .  
Now we will install pnpjs and pnp-spfx-controls-react as shown below: 
  1. npm install @pnp/sp --save      
  2. npm install @pnp/spfx-property-controls --save --save-exact  
Now go to the src > webparts > webpart > components > I{webpartname}Props.ts file,
 
Here we will use control PropertyFieldSitePicker to get sites of current sharepoint context.
  1. import { WebPartContext } from "@microsoft/sp-webpart-base";  
  2. import { IPropertyFieldSite } from "@pnp/spfx-property-controls/lib/PropertyFieldSitePicker";  
  3.   
  4. export interface ISpfxFluentuiPivotProps {  
  5.   site: IPropertyFieldSite[];  
  6.   context: WebPartContext  
  7. }  
Create a file I{webpartname}State.ts inside src > webparts > webpart > components and create a state interface as below,
  1. type user = {  
  2.   Title: string;  
  3. }  
  4.   
  5. type group = {  
  6.   Title: string;  
  7. }  
  8.   
  9. export interface ISpfxFluentuiPivotState {  
  10.   siteUsres: user[];  
  11.   siteGroups: group[];  
  12. }  
Create a Service folder inside src and then in this folder create a file called SPService.ts. And in this file, we will create a service to get site users and site groups as below, 
 
Here site URL comes from the property pane site picker selected site so in the method we will pass the site URL as an argument. 
  1. import { WebPartContext } from "@microsoft/sp-webpart-base";  
  2. import { sp, Web, SiteUsers, SiteGroups } from "@pnp/sp/presets/all";  
  3.   
  4. export class SPService {  
  5.     constructor(private context: WebPartContext) {  
  6.         sp.setup({  
  7.             spfxContext: this.context  
  8.         });  
  9.     }  
  10.   
  11.     public async getCurrentSiteUsers(siteUrl: string): Promise<any> {  
  12.         try {  
  13.             let currentWeb = Web(siteUrl)  
  14.             let users: any[] = await currentWeb.siteUsers();  
  15.             return users;  
  16.         } catch (err) {  
  17.             Promise.reject(err);  
  18.         }  
  19.     }  
  20.   
  21.     public async getCurrentSiteGroups(siteUrl: string): Promise<any> {  
  22.         try {  
  23.             let currentWeb = Web(siteUrl)  
  24.             const groups: any[] = await currentWeb.siteGroups()  
  25.             return groups;  
  26.         }  
  27.         catch (err) {  
  28.             Promise.reject(err);  
  29.         }  
  30.     }  
  31. }  
Now move to the {webpartname}Webpart.ts and create a site property in property pane configuration and pass a context and selected site object property as below, 
  1. import * as React from 'react';  
  2. import * as ReactDom from 'react-dom';  
  3. import { Version } from '@microsoft/sp-core-library';  
  4. import {  
  5.   IPropertyPaneConfiguration,  
  6.   PropertyPaneTextField  
  7. } from '@microsoft/sp-property-pane';  
  8. import { BaseClientSideWebPart } from '@microsoft/sp-webpart-base';  
  9. import * as strings from 'SpfxFluentuiPivotWebPartStrings';  
  10. import SpfxFluentuiPivot from './components/SpfxFluentuiPivot';  
  11. import { ISpfxFluentuiPivotProps } from './components/ISpfxFluentuiPivotProps';  
  12. import { PropertyFieldSitePicker } from '@pnp/spfx-property-controls/lib/PropertyFieldSitePicker';  
  13. import { IPropertyFieldSite } from "@pnp/spfx-property-controls/lib/PropertyFieldSitePicker";  
  14. export interface ISpfxFluentuiPivotWebPartProps {  
  15.   site: IPropertyFieldSite[];  
  16. }  
  17.   
  18. export default class SpfxFluentuiPivotWebPart extends BaseClientSideWebPart<ISpfxFluentuiPivotWebPartProps> {  
  19.   
  20.   public render(): void {  
  21.     const element: React.ReactElement<ISpfxFluentuiPivotProps> = React.createElement(  
  22.       SpfxFluentuiPivot,  
  23.       {  
  24.         context: this.context,  
  25.         site: this.properties.site  
  26.       }  
  27.     );  
  28.   
  29.     ReactDom.render(element, this.domElement);  
  30.   }  
  31.   
  32.   protected onDispose(): void {  
  33.     ReactDom.unmountComponentAtNode(this.domElement);  
  34.   }  
  35.   
  36.   protected get dataVersion(): Version {  
  37.     return Version.parse('1.0');  
  38.   }  
  39.   
  40.   protected getPropertyPaneConfiguration(): IPropertyPaneConfiguration {  
  41.     return {  
  42.       pages: [  
  43.         {  
  44.           header: {  
  45.             description: strings.PropertyPaneDescription  
  46.           },  
  47.           groups: [  
  48.             {  
  49.               groupName: strings.BasicGroupName,  
  50.               groupFields: [                  
  51.                 PropertyFieldSitePicker('site', {  
  52.                   label: 'Select sites',  
  53.                   initialSites: this.properties.site,  
  54.                   context: this.context,  
  55.                   deferredValidationTime: 500,  
  56.                   onPropertyChange: this.onPropertyPaneFieldChanged,  
  57.                   properties: this.properties,  
  58.                   key: 'sitesFieldId'  
  59.                 })  
  60.               ]  
  61.             }  
  62.           ]  
  63.         }  
  64.       ]  
  65.     };  
  66.   }  
  67. }   
Move to the {webpartname}.tsx file and then bind the service using current context and the call service to get users and groups for the selected site and set values in the state and render it in as a pivot/tab format as below,  
  • We will import all necessary libraries. 
  • Create a constructor and set an empty value in a state and bind the service.
  • Create functions called getSiteUsres() and getSiteGroups() by calling the services and set the data in states.
  • Create a function componentDidUpdate() to render data while property is update.
  • Render data in pivot by mapping a states. 
    1. import * as React from 'react';    
    2. import styles from './SpfxFluentuiPivot.module.scss';    
    3. import { ISpfxFluentuiPivotProps } from './ISpfxFluentuiPivotProps';    
    4. import { ISpfxFluentuiPivotState } from './ISpfxFluentuiPivotState';    
    5. import { SPService } from '../../service/SPService';    
    6. import * as strings from 'SpfxFluentuiPivotWebPartStrings';    
    7. import { PivotItem, IPivotItemProps, Pivot } from 'office-ui-fabric-react/lib/Pivot';    
    8. import { Label, ILabelStyles } from 'office-ui-fabric-react/lib/Label';    
    9. import { IStyleSet } from 'office-ui-fabric-react/lib/Styling';    
    10.     
    11. const labelStyles: Partial<IStyleSet<ILabelStyles>> = {    
    12.   root: { marginTop: 10, marginLeft: 10 },    
    13. };    
    14.     
    15. export default class SpfxFluentuiPivot extends React.Component<ISpfxFluentuiPivotProps, ISpfxFluentuiPivotState> {    
    16.     
    17.   private _spService: SPService;    
    18.     
    19.   constructor(props: ISpfxFluentuiPivotProps) {    
    20.     super(props);    
    21.     this.state = {    
    22.       siteUsres: [],    
    23.       siteGroups: [],    
    24.     }    
    25.     this._spService = new SPService(this.props.context);    
    26.   }    
    27.     
    28.   public componentDidMount() {    
    29.     this.getSiteGroups();    
    30.     this.getSiteUsres();    
    31.   }    
    32.     
    33.   public async getSiteUsres() {    
    34.     if (this.props.site && this.props.site.length) {    
    35.       let siteUrl = this.props.site[0].url;    
    36.       let users = await this._spService.getCurrentSiteUsers(siteUrl);    
    37.       this.setState({ siteUsres: users });    
    38.     }    
    39.   }    
    40.     
    41.   public async getSiteGroups() {    
    42.     if (this.props.site && this.props.site.length) {    
    43.       let siteUrl = this.props.site[0].url;    
    44.       let groups = await this._spService.getCurrentSiteGroups(siteUrl);    
    45.       this.setState({ siteGroups: groups });    
    46.     }    
    47.   }    
    48.     
    49.   public componentDidUpdate(prevProps: ISpfxFluentuiPivotProps) {    
    50.     if (prevProps.site !== this.props.site) {    
    51.       this.getSiteGroups();    
    52.       this.getSiteUsres();    
    53.     }    
    54.   }    
    55.     
    56.   public render(): React.ReactElement<ISpfxFluentuiPivotProps> {    
    57.     return (    
    58.       <React.Fragment>    
    59.         {    
    60.           this.props.site && this.props.site.length ?    
    61.             <React.Fragment>    
    62.               <Label>Selected Site: {this.props.site[0].title}</Label>    
    63.               <Pivot aria-label="Count and Icon Pivot Example">    
    64.                 <PivotItem headerText={strings.SiteUserLabel}>    
    65.                   {this.state.siteUsres.map((value) =>    
    66.                     <Label styles={labelStyles}>{value.Title}</Label>    
    67.                   )}    
    68.                 </PivotItem>    
    69.                 <PivotItem headerText={strings.SiteGroupsLabel}>    
    70.                   {this.state.siteGroups.map((value) =>    
    71.                     <Label styles={labelStyles}>{value.Title}</Label>    
    72.                   )}    
    73.                 </PivotItem>    
    74.               </Pivot>    
    75.             </React.Fragment>    
    76.             : <Label>{strings.ErrorMessageLabel}</Label>}    
    77.       </React.Fragment>    
    78.     );    
    79.   }    
    80. }    
Now serve the application using the below command,
  1. gulp serve  
Now test the webpart in SharePoint-SiteURL + /_layouts/15/workbench.aspx.
 
Output
 
Output - Pivot/Tab
 
Find the full source code here.
 

Summary

 
In this article, we have seen how to implement pivot control of fluent UI in spfx webpart.
 
I hope this helps.
 
Sharing is caring!