I have a web part that displays a filtered list of links based on the logged on users profile properties. Its working well, but I cannot work out the best way of adding pagination. The list is never going to be very long, so I would expect most users to see 10 - 15 links, so I am trying to implement each 'page' to 5 items.
I have a JQuery version that uses very simple pagination using the following logic
Global vars
pageSize = 5; pageIndex = items.length/pageSize; firstItem = 0; lastItem = 5;
Next button:
firstItem = firstItem + pageSize; lastItem = lastItem + pageSize;
Previous button:
firstItem = firstItem - pageSize; lastItem = lastItem - pageSize;
I'm not sure how to implement this in the spfx version! So far, all I have managed to do is to wire up the next and previous buttons to event listeners. I can't work out how to do the rest - any one have ideas as to the simplest way to implement this?
Here is my code
import * as React from 'react';
import * as ReactDom from 'react-dom';
import styles from './LinksWp.module.scss';
import { ILinksWpProps } from './ILinksWpProps';
import { escape } from '@microsoft/sp-lodash-subset';
import pnp, { List, RenderListDataOptions } from "sp-pnp-js";
import { setup, Web, NodeFetchClient } from "sp-pnp-js";
import { ClassListItems, ClassListItemLabels } from './ClassListItem';
import { ISPListItem, ISPLabel } from './IListItems';
import { sp } from '@pnp/sp';
import { SPFetchClient } from "@pnp/nodejs";
import {
BaseComponent,
DefaultButton,
DetailsList,
IColumn,
IDetailsHeaderProps,
IDetailsList,
IGroup,
IRenderFunction,
IToggleStyles,
mergeStyles,
Toggle
} from 'office-ui-fabric-react';
const fontSize = {
fontSize: '30px',
};
let myIconClass = '';
let totalItems;
let num=0;
let pageSize;
let pagePrev = 0;
let pageNext = 5;
const mySpan = {
paddingLeft: '20px',
verticalAlign: 'top'
};
export default class LinksWp extends React.Component<ILinksWpProps, any> {
domElement: any;
public constructor(props:ILinksWpProps,any)
{
super(props);
this.state={
items:[],
i: []};
}
public render(): React.ReactElement<ILinksWpProps> {
return (
<div><span role="heading" aria-level="2" className={styles.myLargeFontClass}>{this.props.description}</span><p></p>
<div><ul className={styles.myUl}>{
this.state.items.sort( (a, b) =>{
return a.Desc == b.URL.Desc ? 0 : a.Desc < b.Desc ? -1 : 1;
})
.map((item:ISPListItem)=>{
pageSize=4;
item.arrayID = num++;
if(item.LinkType.includes("External")){myIconClass = "ms-Icon ms-Icon--Globe"};
if(item.LinkType.includes("SharePoint")){myIconClass = "ms-Icon ms-Icon--SharepointLogoInverse"};
if(item.LinkType.includes("Excel")){myIconClass = "ms-Icon ms-Icon--ExcelLogoInverse16"};
if(item.LinkType.includes("Word")){myIconClass = "ms-Icon ms-Icon--WordLogoInverse16"};
if(item.LinkType.includes("PowerPoint")){myIconClass = "ms-Icon ms-Icon--PowerPointLogo"};
if(item.LinkType.includes("PDF")){myIconClass = "ms-Icon ms-Icon--PDF"};
if(item.arrayID>=0 || item.arrayID <=totalItems-pageSize){
return(
<li><a href={item.URL}><i className={myIconClass} style={fontSize} aria-hidden='true'></i><span style={mySpan}>{item.Desc}{item.arrayID}</span></a></li>
);
}
})}
</ul><button id='MyBtnNext' className={styles.button}>Next..</button>
<button id='MyBtnPrev' className={styles.button}>Next..</button></div>
</div>
);
}
public componentDidMount(){
this._getListItems();
}
private next():any {
//alert(totalItems);
}
private prev():any {
//alert(totalItems);
}
public _getListItems():void
{
let clickEvent= document.getElementById('MyBtNext')
clickEvent.addEventListener("click", (e: Event) => this.next());
let clickEvent= document.getElementById('MyBtPrev')
clickEvent.addEventListener("click", (e: Event) => this.prev());
const myprops = [];
const profile = sp.profiles.myProperties.get()
.then(userprops => {
userprops = userprops.UserProfileProperties;
userprops.forEach(myprop => {
if (myprop.Key == "Office") {
myprops.push(myprop.Value);
}
if (myprop.Key == "Geography") {
myprops.push(myprop.Value);
}
if (myprop.Key == "Country") {
myprops.push(myprop.Value);
}
if (myprop.Key == "FunctionRegion") {
myprops.push(myprop.Value);
}
});
console.log(myprops);
let locationVal = myprops[0];
let functionVal = myprops[1];
let countryVal = myprops[2];
let geogVal = myprops[3];
let camlview: any;
camlview = "<View><Query><Where><Or><Contains><FieldRef Name='_Location1' /><Value Type='TaxonomyFieldTypeMulti'>" + locationVal + "</Value></Contains>";
camlview += "<Or><Contains><FieldRef Name='_Geography' /><Value Type='TaxonomyFieldTypeMulti'>" + geogVal + "</Value></Contains>";
camlview += "<Or><Contains><FieldRef Name='_Region1' /><Value Type='TaxonomyFieldTypeMulti'>" + functionVal + "</Value></Contains>";
camlview += "<Or><Contains><FieldRef Name='_Function1' /><Value Type='TaxonomyFieldTypeMulti'>" + functionVal + "</Value></Contains>";
camlview += "<Contains><FieldRef Name='_Function1' /><Value Type='TaxonomyFieldTypeMulti'>Global</Value></Contains></Or></Or></Or></Or></Where></Query>";
camlview += "<ViewFields><FieldRef Name='Title' /><FieldRef Name='ComplianceAssetId' /><FieldRef Name='Comments' /><FieldRef Name='_Function1' /><FieldRef Name='_Region1' /><FieldRef Name='_Geography' /><FieldRef Name='_Location1' /><FieldRef Name='ID' /><FieldRef Name='ContentType' /><FieldRef Name='Modified' /><FieldRef Name='Created' /><FieldRef Name='Author' /><FieldRef Name='Editor' /><FieldRef Name='_UIVersionString' /><FieldRef Name='Attachments' /><FieldRef Name='Edit' /><FieldRef Name='LinkTitleNoMenu' /><FieldRef Name='LinkTitle' /><FieldRef Name='DocIcon' /><FieldRef Name='ItemChildCount' /><FieldRef Name='FolderChildCount' /><FieldRef Name='_ComplianceFlags' /><FieldRef Name='_ComplianceTag' /><FieldRef Name='_ComplianceTagWrittenTime' /><FieldRef Name='_ComplianceTagUserId' /><FieldRef Name='_IsRecord' /><FieldRef Name='AppAuthor' /><FieldRef Name='AppEditor' /><FieldRef Name='URL' /><FieldRef Name='URLwMenu' /><FieldRef Name='URLNoMenu' /><FieldRef Name='LinkType' /></ViewFields>";
camlview += "<QueryOptions /><RowLimit>1000</RowLimit></View>";
sp.web.lists.getByTitle(this.props.description).renderListDataAsStream({
RenderOptions: RenderListDataOptions.ListData,
ViewXml : camlview
//Paging: 'Paged=TRUE&p_ID=' + pageID
}).then
((response: any)=>{
console.log(response)
let listItemCollection = response.Row.map(
item=>new ClassListItems(item)
);
this.setState({items: listItemCollection});
totalItems = this.state.items.length
}
);
});
}
}
'''