Articles

Saved for later items web part in SharePoint Online SPFX

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.
Saved for later pages SharePOint online spfx

SP Home Service api

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
Page Views : 112    Published Date :Sep 22,2019   Author :Mukesh Tiwari
Please Share this page

Popular Articles

Loading...
Like every other website we use cookies. By using our site you acknowledge that you have read and understand our Cookie Policy, Privacy Policy, and our Terms of Service. Learn moreGot it!