Using Sharepoint Online workbench my webpart which is very simple can’t display and throw an error as soon as i use import
Hello,
each time i tried to launch my webpart though the workbench i got this error, i dont understand why.:
`Cannot read properties of undefined (reading ‘id’)
PILE DES APPELS :
TypeError: Cannot read properties of undefined (reading ‘id’)
at https://res-1.cdn.office.net/files/sp-client/sp-webpart-workbench-assembly_fr-fr_28f6472cc264e6dc475aa6d735e23162.js:196:11058
at new Promise ()
at e.loadComponent (https://res-1.cdn.office.net/files/sp-client/sp-webpart-workbench-assembly_fr-fr_28f6472cc264e6dc475aa6d735e23162.js:196:11026)
at https://res-1.cdn.office.net/files/sp-client/sp-webpart-workbench-assembly_fr-fr_28f6472cc264e6dc475aa6d735e23162.js:196:13234
at async Promise.all (index 0)`.
When i delete the 2 imports
import TauxPourGc from ‘./TauxPourGc’;
import { ITfaTauxProps } from ‘./../AssetsCommun/ITfaTauxProps’;
my webpart worked .But when i use these two imports and i create a custom function render i got this error.
The version of Node is V18.20.3 the build toold version is 3.18.1;this is for sharepoint online so i used 1.19.0 spfx version
Here is the code of my webpart
ProdTauxGcWebParts.ts
import { Version } from '@microsoft/sp-core-library';
import {
type IPropertyPaneConfiguration,
PropertyPaneTextField
} 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 './ProdTauxGcWebPart.module.scss';
import * as strings from 'ProdTauxGcWebPartStrings';
import {SPFI } from "@pnp/sp";
import { getSP } from './pnpjsConfig';
//import "@pnp/sp/lists";
//import "@pnp/sp/items";
//import "@pnp/sp/webs";
import TauxPourGc from './TauxPourGc';
import { ITfaTauxProps } from './../AssetsCommun/ITfaTauxProps';
import * as React from 'react';
import * as ReactDom from 'react-dom';
export interface IProdTauxGcWebPartProps {
description: string;
_tauxAvant: string;
_tauxApres: string;
_comparaison: string;
_libelle: string;
_tag: string;
}
export default class ProdTauxGcWebPart extends BaseClientSideWebPart<IProdTauxGcWebPartProps> {
private _isDarkTheme: boolean = false;
private _environmentMessage: string = '';
public sp: SPFI;
public renderold(): void {
const element: React.ReactElement<ITfaTauxProps> = React.createElement(
TauxPourGc,
{
tauxAvant: this.properties._tauxAvant,
tauxApres: this.properties._tauxApres,
comparaison: this.properties._comparaison,
libelle: this.properties._libelle,
tag: this.properties._tag
}
);
console.log('render create taux apres' + this.properties._tauxApres);
ReactDom.render(element, this.domElement);
}
public render(): void {
console.log('render');
// console.log(TauxPourGc.toString());
this.domElement.innerHTML = `
<section class="${styles.prodTauxGc} ${!!this.context.sdks.microsoftTeams ? styles.teams : ''}">
<div 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>${escape(this.properties.description)}</strong></div>
</div>
<div>
<h3>Welcome to SharePoint Framework!</h3>
<p>
The SharePoint Framework (SPFx) is a extensibility model for Microsoft Viva, Microsoft Teams and SharePoint. It's the easiest way to extend Microsoft 365 with automatic Single Sign On, automatic hosting and industry standard tooling.
</p>
<h4>Learn more about SPFx development:</h4>
<ul class="${styles.links}">
<li><a href="https://aka.ms/spfx" target="_blank">SharePoint Framework Overview</a></li>
<li><a href="https://aka.ms/spfx-yeoman-graph" target="_blank">Use Microsoft Graph in your solution</a></li>
<li><a href="https://aka.ms/spfx-yeoman-teams" target="_blank">Build for Microsoft Teams using SharePoint Framework</a></li>
<li><a href="https://aka.ms/spfx-yeoman-viva" target="_blank">Build for Microsoft Viva Connections using SharePoint Framework</a></li>
<li><a href="https://aka.ms/spfx-yeoman-store" target="_blank">Publish SharePoint Framework applications to the marketplace</a></li>
<li><a href="https://aka.ms/spfx-yeoman-api" target="_blank">SharePoint Framework API reference</a></li>
<li><a href="https://aka.ms/m365pnp" target="_blank">Microsoft 365 Developer Community</a></li>
</ul>
</div>
</section>`;
}
protected onInit(): Promise<void> {
console.log('onInit NEW GC ');
this.sp = getSP(this.context);
console.log('onInit NEW GC ' + getSP.toString());
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: strings.PropertyPaneDescription
},
groups: [
{
groupName: strings.BasicGroupName,
groupFields: [
PropertyPaneTextField('description', {
label: strings.DescriptionFieldLabel
})
]
}
]
}
]
};
}
}
TauxPourGc.tsx
import * as React from 'react';
import styles from './../../AssetsCommun/TauxWebPart.module.scss';
import type { ITfaTauxProps } from './../AssetsCommun/ITfaTauxProps';
import FlecheBlancheHaut from './../../AssetsCommun/FlecheBlancheHaut.png';
import FlecheBlancheBas from './../../AssetsCommun/FlecheBlancheBas.png';
import FlecheBlancheMilieu from './../../AssetsCommun/FlecheBlancheEqual.png';
export default class TauxPourGc extends React.Component<ITfaTauxProps, {}> {
private getTag(): string {
console.log('getTag : ' + this.props.tag);
return this.props.tag;
}
private getTauxActuel(): string {
console.log('getTauxActuel : ' + this.props.tauxApres);
return this.props.tauxApres;
}
private getLibelle(): string {
console.log('getLibelle : ' + this.props.libelle);
return this.props.libelle;
}
private getTauxAvant(): string {
console.log('getTauxAvant : ' + this.props.tauxAvant);
return this.props.tauxAvant;
}
private getArrowStyle(): JSX.Element {
console.log('getArrowStyle function: ');
if (this.props.tauxAvant !== undefined) {
console.log('getArrowStyle function inside: ');
console.log('getArrowStyle tauxAvant: ' + this.props.tauxAvant);
console.log('getArrowStyle tauxApres: ' + this.props.tauxApres);
const _TauxavantBase: string = this.props.tauxAvant.toString();
const _TauxapresBase: string = this.props.tauxApres.toString();
console.log('getArrowStyle _TauxavantBaseCustom: ' + _TauxavantBase);
console.log('getArrowStyle _TauxapresBaseCustom: ' + _TauxapresBase);
const tauxAvantFormatted = _TauxavantBase.replace(',', '.');
const tauxApresFormatted = _TauxapresBase.replace(',', '.');
const _LibelleBase: string = this.props.libelle.toString();
console.log('getArrowStyle _LibelleBaseCustom: ' + _LibelleBase);
const _ComparaisonBase: string = this.props.comparaison.toString();
console.log('getArrowStyle _ComparaisonBaseCustom: ' + _ComparaisonBase);
const _Tauxavant = parseFloat(tauxAvantFormatted);
const _Tauxapres = parseFloat(tauxApresFormatted);
if (!isNaN(_Tauxavant) && !isNaN(_Tauxapres)) {
if (_Tauxapres < _Tauxavant) {
console.log('_Tauxapres < _Tauxavant');
return <img src={FlecheBlancheHaut} alt="Fleche Haut" />;
} else if (_Tauxapres > _Tauxavant) {
console.log('__Tauxapres > _Tauxavant');
return <img src={FlecheBlancheBas} alt="Fleche Bas" />;
} else {
console.log('__Tauxapres = _Tauxavant');
return <img src={FlecheBlancheMilieu} alt="Fleche Milieu" />;
}
}
return <img src={FlecheBlancheMilieu} alt="Fleche Milieu" />;
}
return <div>Erreur</div>;
}
public render(): React.ReactElement<ITfaTauxProps> {
console.log('render inside ');
const arrowStyle: JSX.Element = this.getArrowStyle();
return (
<div className={styles.preventionDisplay}>
<div className={styles.rectangle}>
<div className={styles.texteHautTitre}>
<span>Génie Civil France</span>
</div>
<div className={styles.texteHautTag}>
<span>{this.getTag()}</span>
</div>
<div className={styles.texteHautLib}>
<span>{this.getLibelle()}</span>
</div>
<div className={styles.row}>
<div className={styles.row}>
<div className={styles.arrowCustom}>
{arrowStyle && (
<span>
{arrowStyle}
</span>
)}
</div>
<div className={styles.avant}>
<span>{this.getTauxActuel()}</span>
</div>
<div className={styles.separator}/>
</div>
<div className={styles.column}>
<div className={styles.pcustom}>
</div>
<div className={styles.pcustom}>
{this.getTauxAvant()}
</div>
<div className={styles.pcustom}>La période</div>
<div className={styles.pcustom}>précédente</div>
</div>
</div>
</div>
</div>
);
}
}
pnpjsConfig.ts
import { WebPartContext } from "@microsoft/sp-webpart-base";
// import pnp and pnp logging system
import { spfi, SPFI, SPFx } from "@pnp/sp";
import { LogLevel, PnPLogging } from "@pnp/logging";
import "@pnp/sp/webs";
import "@pnp/sp/lists";
import "@pnp/sp/items";
import "@pnp/sp/batching";
// eslint-disable-next-line no-var
var _sp: SPFI ;
export const getSP = (context?: WebPartContext): SPFI => {
console.log('getSP getSP');
if (!!context) { // eslint-disable-line eqeqeq
//You must add the @pnp/logging package to include the PnPLogging behavior it is no longer a peer dependency
// The LogLevel set's at what level a message will be written to the console
_sp = spfi().using(SPFx(context)).using(PnPLogging(LogLevel.Warning));
}
return _sp;
};
ITfaTauxProps.ts
export interface ITfaTauxProps {
tauxAvant: string;
tauxApres: string;
comparaison: string;
libelle: string;
tag: string;
}