Saved for later items web part in SharePoint Online SPFX
In this article we will create a webpart to show saved for later pages in SharePoint online using SharePoint Framework or spfx.
What are saved for later pages
Microsoft have released a new feature in SharePoint online which can be used to save the link of SharePoint pages for later. It is like book mark.
When you save a page for later then a link to that page is saved some where.
When you browse a page then in the bottom next to views there is save for later. To save a page for later you can click on the icon next to save for later. as shown in the image below.
this web part uses sp home service api to access saved for later pages data. for more information have a look on
https://tutorialsinhand.com/Articles/How-to-fetch-saved-pages-in-sharepoint-online.aspx
Creating SharePoint Framework or SPFX web part
Open a command prompt and navigate to the folder you have created for creating the solution and type
yo @microsoft/sharepoint
Which base line package you want to target your web part :choose SharePoint Online Only (Latest)
Where do you want to place files : choose current folder
Do you want to allow tenant admin the choice of being able to deploy the solution to all sites immediately .. : Answer y
Which type of client side component to create : WebPart
What is your web part name ? : saveForLaterWebPart
And then press Enter and choose React option when asked for framework options.
After scaffolding completed open the web part by typing code . in the command prompt.
So we have created our web part. lets create some types need to get saved for later pages.
Create needed types
Create a folder named types in src/webpart folder and create a file named types.ts and paste below code.
export interface IParentReference
{
WebId:string;
IndexId:string;
SiteId:string;
Type:string;
}
export interface IDemoSite
{
Id:string;
Url:string;
Title:string;
Type:string;
}
export interface IActivityItem
{
Type:string;//1. NewsArticle 2. ModernPage
Title:string;
Url:string;
UniqueId:string;
StaticTeaser:string;
Site?:IDemoSite;
SavedForLater:boolean;
FileExtension:string;
ContentClass:string;
ContentTypeId:string;
ListItemId:number;
ImageUrl:string;
}
export interface ISaveForLaterItem
{
Id:string;
ParentReference:IParentReference;
ActivityItem:IActivityItem;
Type:string;
}
export interface ITokenItem
{
access_token:string;
resource:string;
}
In this code the main type is ISaveForLaterItem which contains
Id: unique id the item
ParentReference : parent site and web details
ActivityItem : details the page
Type : string which is either NewsArticle or ModernPage at this time
Other main type is ITokenItem which contains two properties as below
access_token : token string
resource : url of the home services api
Great!! We have created the needed types. Lets create a service to get the data.
Create a service to get the data
In src/webparts folder create a Services and then create a file named SaveForLaterItemService.ts in this folder and paste below code.
import {ITokenItem,ISaveForLaterItem} from '../types/types';
import { WebPartContext } from "@microsoft/sp-webpart-base";
import { HttpClientConfiguration, HttpClient, IHttpClientOptions, HttpClientResponse,SPHttpClient ,SPHttpClientResponse} from "@microsoft/sp-http";
import { Guid } from '@microsoft/sp-core-library';
export class SaveForLaterItemService
{
public static getToken(client:SPHttpClient,baseurl:string):Promise<ITokenItem>
{
return client.get(baseurl+"/_api/sphomeservice/context/Token",SPHttpClient.configurations.v1).then((response:SPHttpClientResponse)=>{
return response.json().then((responseJson:any)=>{
return new Promise<ITokenItem>((resolve,reject)=>{
resolve(responseJson);
});
});
});
}
public static getSaveForItems(context:WebPartContext):Promise<ISaveForLaterItem[]>
{
// 1. get token 2. issue home service requiest
return this.getToken(context.spHttpClient, context.pageContext.web.absoluteUrl ).then((token:ITokenItem)=>{
let url:string =token.resource+ "/api/v1/documents/saveForLater?start=0&count=100";
var options : IHttpClientOptions =
{
headers:{
'authorization': `Bearer ${token.access_token}`,
'sphome-apicontext': `{"PortalUrl":"${context.pageContext.site.absoluteUrl}"}`
}
};
return context.httpClient.get(url,HttpClient.configurations.v1,options).then((response:HttpClientResponse)=>{
return response.json().then((responsejson:any)=>{
return new Promise<ISaveForLaterItem[]>((resolve)=>{
resolve(responsejson.Activities);
});
});
});
});
}
}
This code contains two methods , one for getting token and other for getting save for later items.
Coding web part
Now we have created required types and service to get the data. now lets do some coding in the webpart.
Coding webpart involves two things. as our web part is react based so we need to modify the react component to accept items and modify webpart to supply those items.
open ISaveForLaterItemsWebpartProps.ts from your webpart's components folder and paste below code.
import { ISaveForLaterItem } from "../../types/types";
export interface ISaveForLaterItemsWebpartProps {
items:ISaveForLaterItem[];
}
Save this file. And open your react component named SaveForLaterItemsWebpart.tsx in this folder and paste below code.
import * as React from 'react';
import styles from './SaveForLaterItemsWebpart.module.scss';
import { ISaveForLaterItemsWebpartProps } from './ISaveForLaterItemsWebpartProps';
import { escape } from '@microsoft/sp-lodash-subset';
import { DetailsList, IColumn, CheckboxVisibility } from 'office-ui-fabric-react/lib/DetailsList';
import {ISaveForLaterItem} from '../../types/types';
export default class SaveForLaterItemsWebpart extends React.Component<ISaveForLaterItemsWebpartProps, {}> {
private _detailListRenderColumns : IColumn[]=[
{
key:'icon',
name:"",
maxWidth:71,
minWidth:16,
onRender:(item:ISaveForLaterItem)=>{
// tslint:disable-next-line:jsx-no-lambda
return (<div style={{width:'71px'}}><img src="https://spoprod-a.akamaihd.net/files/fabric/assets/item-types-fluent/16/spo.png" width='16' height='16'/></div>);
}
} as IColumn,
{
key:'Title',
name:"Title",
isRowHeader:true,
onRender:(item:ISaveForLaterItem)=>{
// tslint:disable-next-line:jsx-no-lambda
return ( <a target="_blank" title={item.ActivityItem.Title} href={item.ActivityItem.Url} >{item.ActivityItem.Title}</a>);
}
} as IColumn
];
public render(): React.ReactElement<ISaveForLaterItemsWebpartProps> {
return (
<div style={{marginTop:'21px'}}><DetailsList key="ID" items={this.props.items} columns={this._detailListRenderColumns} checkboxVisibility={CheckboxVisibility.hidden}/></div>
);
}
}
So our component is ready, next we need to update the webpart.
Open your web part file SaveForLaterItemsWebpartWebPart.ts and replace the code with below code.
import * as React from 'react';
import * as ReactDom from 'react-dom';
import { Version } from '@microsoft/sp-core-library';
import { BaseClientSideWebPart } from '@microsoft/sp-webpart-base';
import {
IPropertyPaneConfiguration,
PropertyPaneTextField
} from '@microsoft/sp-property-pane';
import * as strings from 'SaveForLaterItemsWebpartWebPartStrings';
import SaveForLaterItemsWebpart from './components/SaveForLaterItemsWebpart';
import { ISaveForLaterItemsWebpartProps } from './components/ISaveForLaterItemsWebpartProps';
import {SaveForLaterItemService} from '../Services/SaveForLaterItemService';
import {ISaveForLaterItem} from '../types/types';
export interface ISaveForLaterItemsWebpartWebPartProps {
description: string;
}
export default class SaveForLaterItemsWebpartWebPart extends BaseClientSideWebPart<ISaveForLaterItemsWebpartWebPartProps> {
public render(): void {
this.context.statusRenderer.displayLoadingIndicator(this.domElement,"Loading data..");
SaveForLaterItemService.getSaveForItems(this.context).then((items:ISaveForLaterItem[])=>{
const element: React.ReactElement<ISaveForLaterItemsWebpartProps > = React.createElement(
SaveForLaterItemsWebpart,
{
items:items
}
);
ReactDom.render(element, this.domElement);
});
}
protected onDispose(): void {
ReactDom.unmountComponentAtNode(this.domElement);
}
protected get dataVersion(): Version {
return Version.parse('1.0');
}
protected getPropertyPaneConfiguration(): IPropertyPaneConfiguration {
return {
pages: [
{
header: {
description: strings.PropertyPaneDescription
},
groups: [
{
groupName: strings.BasicGroupName,
groupFields: [
PropertyPaneTextField('description', {
label: strings.DescriptionFieldLabel
})
]
}
]
}
]
};
}
}
Save all pages and run the serve the solution using gulp serve to see the result.
Note : you must see this in hosted workbench because webpart will not work in local workbench
To download the code you can go to github
https://github.com/mukeshhope/spfxcomponents
Would you like to see your article here on tutorialsinhand.
Join
Write4Us program by tutorialsinhand.com
About the Author
Mukesh Tiwari
Always ready to learn new technologies, A problem solver, exhibit to do attitude. Having around 10+ years of experience of development and management skills. I believe don't just set random goals but right goals suited for you.
Page Views :
Published Date :
Jun 27,2020