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?
setTimeout
inside thecomponentDidMount
event instead ofrender
. You could try puttingconsole.log
s in there to help you debug - put one just before callingsetTimeout
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 therender
function actually gets called.