javascriptreactjstypescriptoffice-jsweb-parts

SharePoint React Webpart vs Office is not defined


I'm trying to create a SPO client-side Webpart in React that would use OfficeJs to start a new e-mail message on the client's desktop (Outlook).

But, no matter what I do, I can't get rid of a "Office is not defined" error.

I've tried many of the solution I could find out there and none has worked. Some dated all the way back to 2016, which felt outdated, but I tried anyway. Here are some links for things I tried.

An error message "'Office' is not defined no-undef" happens if react-script is newer than 3.0.0 https://github.com/microsoft/TypeScript/issues/11420

I also tried working with different packages like @types/office-js (seems to be the current way), and @microsoft/office-js.

The weird thing is that I have an Outlook Add-In (using the new Web Add-In stuff, not the old stuff) where the same calls to Office.something work just fine. I just can't pin point what's missing on the Webpart project.

Can anyone help getting this to work?

Here is what the code looks like:

ReplyEmailWebPart (don't mind the "Reply" here, should be the same"

import * as React from 'react';
import * as ReactDom from 'react-dom';
import { BaseClientSideWebPart } from '@microsoft/sp-webpart-base';
import ReplyEmailComponent from './components/ReplyEmailComponent';

export default class ReplyEmailWebPart extends BaseClientSideWebPart<unknown> {

  public render(): void {
    const element: React.ReactElement<unknown> = React.createElement(ReplyEmailComponent);

    ReactDom.render(element, this.domElement);
  }

  protected onInit(): Promise<void> {
    return super.onInit();
  }

  protected onDispose(): void {
    ReactDom.unmountComponentAtNode(this.domElement);
  }
}

ReplyEmailComponent.tsx

import * as React from 'react';

//import * as Office from 'office-js';

//// <reference types="@types/office-js" />

/* global Office */

export default class ReplyEmailComponent extends React.Component<unknown, {}> {

  public componentDidMount(): void {
    debugger;
    Office.initialize = () => {
      console.log('Office.js initialized');
      // Perform additional initialization tasks here
    };
  }

  private handleClick = (): void => {
    Office.context.mailbox.displayNewMessageForm({
      toRecipients: ['recipient@example.com'],
      subject: 'Test email',
      body: 'Hello, world!',
    });
  };

  public render(): React.ReactElement<unknown> {
    debugger;
    return (
      <section>
        <div>
          <script src="https://appsforoffice.microsoft.com/lib/1.1/hosted/office.js" />
          <button onClick={this.handleClick}>Send Email</button>
        </div>
      </section>
    );
  }
}

package.json

{
  "name": "reply-from-spo-web-part",
  "version": "0.0.1",
  "private": true,
  "main": "lib/index.js",
  "scripts": {
    "build": "gulp bundle",
    "clean": "gulp clean",
    "test": "gulp test"
  },
  "dependencies": {
    "@microsoft/office-js": "^1.1.84",
    "@microsoft/sp-webpart-base": "1.15.2",
    "office-ui-fabric-react": "7.185.7",
    "react": "16.13.1",
    "react-dom": "16.13.1"
  },
  "devDependencies": {
    "@microsoft/rush-stack-compiler-4.5": "0.2.2",
    "@microsoft/sp-build-web": "1.15.2",
    "@types/office-js": "^1.0.318",
    "@types/react": "16.9.51",
    "@types/react-dom": "16.9.8",
    "gulp": "4.0.2"
  }
}

tsconfig.json

{
  "extends": "./node_modules/@microsoft/rush-stack-compiler-4.5/includes/tsconfig-web.json",
  "compilerOptions": {
    "target": "es5",
    "forceConsistentCasingInFileNames": true,
    "module": "esnext",
    "moduleResolution": "node",
    "esModuleInterop": true,
    "jsx": "react",
    "declaration": true,
    "sourceMap": true,
    "experimentalDecorators": true,
    "skipLibCheck": true,
    "outDir": "lib",
    "inlineSources": false,
    "strictNullChecks": false,
    "noUnusedLocals": false,
    "noImplicitAny": true,

    "typeRoots": [
      "./node_modules/@types",
      "./node_modules/@microsoft"
    ],
    "types": [
      "webpack-env",
      "office-js",
      "@types/office-js"
    ],
    "lib": [
      "es5",
      "dom",
      "es2015.collection",
      "es2015.promise"
    ]
  },
  "include": [
    "src/**/*.ts",
    "src/**/*.tsx"
  ]
}

I've tried to clean up the code as much as I could. I started from the yo generator template.

I've created a git repo to make it easier for anyone to help:

https://github.com/eduardomb08/ReplyEmailWebPart


Solution

  • Office.js can only run if it is initialized and it can only initialize inside an add-in in one of the Office suite applications (Outlook, Word, etc.) That's why it works in your Outlook add-in. Add-ins are the only place where calls to Office.js can be made. If the SharePoint page with the webpart is the home page of a task pane in an Office add-in that would work. But if that page is opening anywhere outside of an add-in, calls to Office.js will not work.