1

I have a modern sharepoint online page which show data from multiple custom lists using PnP Modern search web part. the issue with the PnP Modern search web part, is that it does not automatically update the list of items (incase new items are added/deleted to the underlying lists) unless you manually refresh the web page.

so is there a way to auto refresh a modern sharepoint page each let say 5 minutes? the only solution i found is to use something such as :-

https://github.com/pnp/sp-dev-fx-webparts/blob/main/samples/react-script-editor/README.md

but using this appraoch will allow end users to embed whatever script they want which will pose a security issue.. so how i can auto refresh a modern sharepoint page , without the need to embed script and hence allow end users to embed any script they want?

Thanks

EDIT

I built a No framework web part , and i define this inside the .ts file:-

import { Version } from '@microsoft/sp-core-library';
import {
  type IPropertyPaneConfiguration,
  PropertyPaneSlider
} from '@microsoft/sp-property-pane';
import { BaseClientSideWebPart } from '@microsoft/sp-webpart-base';
import type { IReadonlyTheme } from '@microsoft/sp-component-base';
import { escape } from '@microsoft/sp-lodash-subset';

import styles from './AutoRefreshWebPart.module.scss';
import * as strings from 'AutoRefreshWebPartStrings';

export interface IAutoRefreshWebPartProps {
  reloadInterval: number;

}

export default class AutoRefreshWebPart extends BaseClientSideWebPart<IAutoRefreshWebPartProps> {

  private _isDarkTheme: boolean = false;
  private _environmentMessage: string = '';

  public render(): void {

    const interval = (this.properties.reloadInterval || 5) * 60 * 1000;
      setTimeout(() => {
        window.location.reload();
      }, interval);

    this.domElement.innerHTML = `
    <section style="visibility: hidden;Height:5px" class="${styles.autoRefresh} ${!!this.context.sdks.microsoftTeams ? styles.teams : ''}">
      <div style="visibility: hidden" class="${styles.welcome}">
        <img alt="" src="${this._isDarkTheme ? require('./assets/welcome-dark.png') : require('./assets/welcome-light.png')}" class="${styles.welcomeImage}" />
        <h2>Well done, ${escape(this.context.pageContext.user.displayName)}!</h2>
        <div>${this._environmentMessage}</div>
        <div>Web part property value: <strong></strong></div>
      </div>
     
    </section>`;
  }

  protected onInit(): Promise<void> {
    return this._getEnvironmentMessage().then(message => {
      this._environmentMessage = message;
    });
  }



  private _getEnvironmentMessage(): Promise<string> {
    if (!!this.context.sdks.microsoftTeams) { // running in Teams, office.com or Outlook
      return this.context.sdks.microsoftTeams.teamsJs.app.getContext()
        .then(context => {
          let environmentMessage: string = '';
          switch (context.app.host.name) {
            case 'Office': // running in Office
              environmentMessage = this.context.isServedFromLocalhost ? strings.AppLocalEnvironmentOffice : strings.AppOfficeEnvironment;
              break;
            case 'Outlook': // running in Outlook
              environmentMessage = this.context.isServedFromLocalhost ? strings.AppLocalEnvironmentOutlook : strings.AppOutlookEnvironment;
              break;
            case 'Teams': // running in Teams
            case 'TeamsModern':
              environmentMessage = this.context.isServedFromLocalhost ? strings.AppLocalEnvironmentTeams : strings.AppTeamsTabEnvironment;
              break;
            default:
              environmentMessage = strings.UnknownEnvironment;
          }

          return environmentMessage;
        });
    }

    return Promise.resolve(this.context.isServedFromLocalhost ? strings.AppLocalEnvironmentSharePoint : strings.AppSharePointEnvironment);
  }

  protected onThemeChanged(currentTheme: IReadonlyTheme | undefined): void {
    if (!currentTheme) {
      return;
    }

    this._isDarkTheme = !!currentTheme.isInverted;
    const {
      semanticColors
    } = currentTheme;

    if (semanticColors) {
      this.domElement.style.setProperty('--bodyText', semanticColors.bodyText || null);
      this.domElement.style.setProperty('--link', semanticColors.link || null);
      this.domElement.style.setProperty('--linkHovered', semanticColors.linkHovered || null);
    }

  }

  protected get dataVersion(): Version {
    return Version.parse('1.0');
  }

  protected getPropertyPaneConfiguration(): IPropertyPaneConfiguration {
    return {
      pages: [
        {
          header: {
            description: "Configure reload interval"
          },
          groups: [
            {
              groupName: "Settings",
              groupFields: [
                PropertyPaneSlider('reloadInterval', {
                  label: "Reload Interval (minutes)",
                  min: 1,
                  max: 60,
                  value: this.properties.reloadInterval || 5,
                  showValue: true,
                  step: 1
                })
              ]
            }
          ]
        }
      ]
    };

  }
}

I defined the interval to be 1 minute. now when I visited the modern page which have this web part, it will reload after 1 minute, after that no extra reload will happen. could the reason be that I added the web part at the end on the page, and it will not get executed unless the user manually navigates to the end of the page?

7
  • 2
    Couldn't you just build your own "mini" SPFx webpart who's only purpose is to run a timer and refresh the page? You could even expose the amount of time between refreshes as a web part property pane control so it's configurable. Then just add that web part to the same page that the PnP Search webpart is on. That way all the code is contained/packaged and no one can mess with it. It's a bit of overkill, but would get the job done, no? Commented Aug 27 at 22:20
  • @DylanCristy thanks foe the help, do you know if there is any link which can help me to achieve this? Commented Aug 28 at 0:25
  • Have you ever built your own SPFx webpart before? Commented Aug 28 at 13:13
  • 1
    Not sure exactly why it is not working... I usually do React based stuff, so I would be looking to put the setTimeout inside the componentDidMount event instead of render. You could try putting console.logs in there to help you debug - put one just before calling setTimeout to log the interval that it's about to set as a timeout, and then put one inside the timeout function just before calling the reload. That way you would have some visibility into when the render function actually gets called. Commented Aug 28 at 16:17
  • 1
    I believe Microsoft introduced lazy loading of components on the page, so that's why you're web part doesn't get loaded until you scroll it into view. If you are worried about adding your web part to the top of the page because it would leave some additional white space in the layout above your other web parts you can add some logic to hide the web parts parent container when the page is not in edit mode. Commented Aug 30 at 6:13

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.