SPFX using Office UI Fabric to Show all the list items

We are going to create a UI as below.

https://admin.microsoft.com/Adminportal/Home#/users

Using MSGraph API fetch the users from Microsoft Admin page portal, and display on the page.



Create react framework

Install MS graph types dependency

 npm install @microsoft/microsoft-graph-types --save-dev

Go to props file in component folder, first we need webpart context.

so import webpart context.

import {WebPartContext} from '@microsoft/sp-webpart-base';

then
export interface IShowAllItemsOfficeUiFabricProps {
  description: string;
  context:WebPartContext;
}

now in main ts file,
we need to pass value to the context,
const element: React.ReactElement<IShowAllItemsOfficeUiFabricProps> = React.createElement(
      ShowAllItemsOfficeUiFabric,
      {
        description: this.properties.description,
        context: this.context
      }
    );

Now we have to create two files
IShowAllUsersState.ts, IUser.ts

we took IUser.ts as one model to make it easy all the properties and store them in state model easily.
We create below interface.
export interface IUser{
    displayName: string;
    givenName: string;
    surname: string;
    mail:string;
    mobilePhone: string;
    userPrincipleName: string;
}

Now go to state.ts file which is IShowAllUsersState.ts

users contains array of IUser interface.

import {IUser} from "./IUser";

export interface IShowAllUserState {
    users: Array<IUser>;
    searchFor:string
}
searchFor is for search in the input.

Now go to .tsx file.
First import IUser interface.
similarly state.ts file, MSGraphClient and MSGraph types
import {IUser} from './IUser';
import { IShowAllUserState } from './IShowAllUsersState';
import {MSGraphClient} from '@microsoft/sp-http';
import * as MicrosoftGraph from '@microsoft/microsoft-graph-types';

import {
  TextField,
  //autobind,
  PrimaryButton,
  DetailsList,
  DetailsListLayoutMode,
  CheckboxVisibility,
  SelectionMode
} from 'office-ui-fabric-react';

Q. When you are using MS Graph API, what all you need to import. We need to import MSGraphClient interface form 'microsoft/sp-http' And MicrosoftGraph types using import statement import * as MicrosoftGraph from '@microsoft/microsoft-graph-types'; Autobind is used for click event handler, hence using it in the code.

one last import statement is ShowAllUsers webpart strings. What it is means go to mystring.d.ts file,
boiler plate code has created a module for us.
why this is important to import is because,  to show the error message if we typed in incorrectly. For example, If I enter user name in text box incorrectly, then it show error message.
what ever properties in IShowAllItemsOfficeUiFabricWebPartStrings the properties and holds to a string. Then this strings are been exported from the module.

Now we are going to add one more property here in the IShowAllItemsOfficeUiFabricWebPartStrings .
to find out the error message if user enter text input incorrectly.

declare interface IShowAllItemsOfficeUiFabricWebPartStrings {
  PropertyPaneDescription: string;
  BasicGroupName: string;
  DescriptionFieldLabel: string;
  SearchFor: string;
  SearchForValidationErrorMessage: string;
}

then go to en-us.js file and there as well with values.
define([], function() {
  return {
    "PropertyPaneDescription": "Description",
    "BasicGroupName": "Group Name",
    "DescriptionFieldLabel": "Description Field",
    "SearchFor": "Search for",
    "SearchForValidationErrorMessage":"Invalid value for 'SearchFor' field"
  }
});

If we want to use the above validation functionality check in our tsx file, we need to import
import * as strings from 'ShowAllItemsOfficeUiFabricWebPartStrings';


Now we need to start our actual implementation in our react component in .tsx file.

We need to pass our state interface and props interface as parameters to our react component.

export default class ShowAllItemsOfficeUiFabric extends React.Component<IShowAllItemsOfficeUiFabricProps,IShowAllUserState> {

  constructor(props:IShowAllItemsOfficeUiFabricProps, state:IShowAllUserState) {
    super(props);
    this.state = {
      users: [],
      searchFor: "Koti Saga"
    };
  }

here, searchFor we provided a default value as "Koti Saga" which will show all items with filter of "Koti Saga" value.

We are using DetailsList as input of fabric UI where we are rendering.
under columns={_userListColumns} is one which we define as any array from IUser.ts

let _userListColumns = [
  {
    key: 'displayName',
    name: 'Display Name',
    fieldName: 'displayName',
    minWidth: 50,
    maxWidth: 150,
    isResizable: true
  }, and so on.. other fields from IUser.ts file
]

onclick for button
<PrimaryButton
            text='Search'
            title='Search'
            onClick={(e)=>this._search(e)}
          />
  public _search=(e)=>{
    this.fetchUserDetails();
  }
onchange for text field
<TextField
          label={strings.SearchFor}
          required={true}
          value={this.state.searchFor}
          onChange={this._onSearchForChanged.bind(this)}
          onGetErrorMessage = {this._getSearchForErrorMessage}
        />

private _onSearchForChanged(event: React.FormEvent<HTMLInputElement | HTMLTextAreaElement>, newValue: string): void {
  //private _onSearchForChanged(newValue: string):void{
    this.setState({
      searchFor:newValue
    });
  }

------------------------------------------------------------------------------
.tsx file code

import * as React from 'react';
import styles from './ShowAllItemsOfficeUiFabric.module.scss';
import { IShowAllItemsOfficeUiFabricProps } from './IShowAllItemsOfficeUiFabricProps';
import { escape } from '@microsoft/sp-lodash-subset';

import {IUser} from './IUser';
import { IShowAllUserState } from './IShowAllUsersState';
import {MSGraphClient} from '@microsoft/sp-http';
import * as MicrosoftGraph from '@microsoft/microsoft-graph-types';

import {
  TextField,
  //autobind,
  PrimaryButton,
  DetailsList,
  DetailsListLayoutMode,
  CheckboxVisibility,
  SelectionMode
} from 'office-ui-fabric-react';
import * as strings from 'ShowAllItemsOfficeUiFabricWebPartStrings';

let _userListColumns = [
  {
    key: 'displayName',
    name: 'Display Name',
    fieldName: 'displayName',
    minWidth: 50,
    maxWidth: 150,
    isResizable: true
  },
  {
    key: 'givenName',
    name: 'Given Name',
    fieldName: 'givenName',
    minWidth: 50,
    maxWidth: 150,
    isResizable: true
  },
  {
    key: 'surname',
    name: 'Sur Name',
    fieldName: 'surname',
    minWidth: 50,
    maxWidth: 150,
    isResizable: true
  },
  {
    key: 'mail',
    name: 'Email',
    fieldName: 'mail',
    minWidth: 50,
    maxWidth: 150,
    isResizable: true
  },
  {
    key: 'mobilePhone',
    name: 'Mobile',
    fieldName: 'mobilePhone',
    minWidth: 50,
    maxWidth: 150,
    isResizable: true
  },
  {
    key: 'userPrincipleName',
    name: 'User Principle',
    fieldName: 'userPrincipleName',
    minWidth: 50,
    maxWidth: 150,
    isResizable: true
  },
];

export default class ShowAllItemsOfficeUiFabric extends React.Component<IShowAllItemsOfficeUiFabricProps,IShowAllUserState> {

  constructor(props:IShowAllItemsOfficeUiFabricProps, state:IShowAllUserState) {
    super(props);
    this.state = {
      users: [],
      searchFor: "Teja"
    };
  }  

  public _search=(e)=>{
    this.fetchUserDetails();
  }

  public componentDidMount():void{
    this.fetchUserDetails();
  }

  private _onSearchForChanged(event: React.FormEvent<HTMLInputElement | HTMLTextAreaElement>, newValue: string): void {
    this.setState({
      searchFor:newValue
    });
  }

  private _getSearchForErrorMessage(value: string):string {
    return(value==null|| value.length==0||value.indexOf(" ")<0)? '':`${strings.SearchForValidationErrorMessage}`;
  }

  public fetchUserDetails():void {
    this.props.context.msGraphClientFactory.getClient().then((client:MSGraphClient):void=>{
      client
      .api('users')
      .version("v1.0")
      .select("*")
      .filter( `startswith(givenname,'${escape(this.state.searchFor)}')`)
      .get((error:any,response,rawResponse?:any)=>{
        if(error){
          console.error("Message is: "+error.message);
          return;
        }

        //Prepare the output array
        var allUsers: Array<IUser> = new Array<IUser>();
        //Map the JSON response to the output array
        response.value.map((item: IUser)=>{
           allUsers.push({
             displayName: item.displayName,
             givenName: item.givenName,
             surname:item.surname,
             mail: item.mail,
             mobilePhone: item.mobilePhone,
             userPrincipleName: item.userPrincipleName
           });
        });

        this.setState({users:allUsers});

      });
    });

  }

  public render(): React.ReactElement<IShowAllItemsOfficeUiFabricProps> {
    return (
      <div className={ styles.showAllItemsOfficeUiFabric }>
       
        <TextField
          label={strings.SearchFor}
          required={true}
          value={this.state.searchFor}
          onChange={this._onSearchForChanged.bind(this)}
          onGetErrorMessage = {this._getSearchForErrorMessage}
        />
        <p className={styles.title}>
          <PrimaryButton
            text='Search'
            title='Search'
            onClick={(e)=>this._search(e)}
          />
        </p>
        {
          (this.state.users!=null && this.state.users.length>0)?
          <p className={styles.row}>
            <DetailsList
              items={this.state.users}
              columns={_userListColumns}
              setKey='set'
              checkboxVisibility={CheckboxVisibility.onHover}
              selectionMode={SelectionMode.single}
              layoutMode={DetailsListLayoutMode.fixedColumns}
              compact={true}
            />
          </p>
          : null
        }

      </div>
    );
  }
}
-----------------Out put UI------------------




Comments