Creating a Teams Tab with SPFx, React.js and Material-UI

Microsoft Teams Tab are very similar to normal SPFx webparts. The webpart logic is still the same, there are just additional steps that can make your app applicable for Teams.

Detailed instructions can be found here under Microsoft Docs. There is a good in-depth documentation by Nanddeep Nachan on C-SharpCorner and by Robert Schouten just to name a couple. I will just highlight some areas that you need to know to get started.

You can start as normal with ‘yo @microsoft/sharepoint’. However, if you are interested in using material-ui I recommend you use ‘yo @pnp/spfx’ as it gives you the option to select the version of typescript you want to use. Since material-ui is a picky one, it needs typescript 3+ so, as of today, you should choose 3.5 during setup. Also make sure you select webpart instead of extension or library.

Once the scaffolding is complete, open the manifest.json file found under src/webparts/{webpart name}/ and in the “supportedHosts” property add “TeamsTab” in the array.

Then in your main WebPart.ts file import the below.

import * as microsoftTeams from '@microsoft/teams-js';

And in your default class define the below.

private _teamsContext: microsoftTeams.Context;

And your onInit method should look similar to the below.

protected onInit(): Promise<any> {
  let retVal: Promise<any> = Promise.resolve();
  if (this.context.microsoftTeams) {
    retVal = new Promise((resolve, reject) => {
      this.context.microsoftTeams.getContext(context => {
        this._teamsContext = context;
        resolve();
      });
    });
  }
  return retVal;
}

Make sure you pass the properties of the teams context in the render method so that React can use them in the next part. You can have conditional areas appearing based on the role of the user viewing the tab.

Now moving to the React part. Import the below in the main .tsx file.

import Button from '@material-ui/core/Button';
import { withStyles } from '@material-ui/core/styles';

Material-UI works with a different type of style generation other than SCSS allowing you to theme the UI in your own way. For my webpart I defined this constant for my button, but you can define more elements if you need.

const CustomButton = withStyles((theme) => ({
	root: {
		color: 'white',
		borderColor: 'white',
		margin: '3px auto',
		display: 'block'
	}
}))(Button);

Then initialize SP using ‘sp.setup’ to either link it to the context base url or the specific site you want this webpart to fetch the information you want to display. In my case, I wanted this webpart to be installed in multiple teams and fetch from a fixed collaboration site.

Coming back to the conditional display of elements based on the role within the team, I used the below. I am showing a button only to the Owners of the team in order to manage the trainees. A double condition is used here because I needed to first check if the teamContext exists, and then check the user role within the team context to display the button.

{this.props.teamContext ? (
  this.props.teamContext.userTeamRole === 0 ? (
    <CustomButton
      variant="outlined"
      color="primary"
      onClick={() => this.openAdmin()}
    >
      Manage Trainees
    </CustomButton>
  ) : (
    ""
  )
) : (
  ""
)}

This is my openAdmin method for reference. This just opens a link in a new window.

public openAdmin = () => {
	window.open('https://tenant.sharepoint.com/sites/teamname/Lists/Map/', '_blank');
};

Have in mind that you can’t really see the teamContext if you are running ‘gulp serve’ because team context only appears within Teams, not under the workbench.

One final step you need to take before you deploy the solution is to create the team tab manifest file. Create the file under the teams folder of your app and call it manifest.json. You can find a sample of the manifest file from Microsoft Docs.

Webpart Deployment

Now you still deploy the webpart by bundling and packaging with –ship, so that is still the same, but in the SP App Catalogue there is an extra option in the ribbon called ‘Sync to Teams’. You need to be a tenant admin to do this, being only a SharePoint admin will not do the trick. You only need to do this once for every webpart. Afterwards, when you need to update the webpart, just replacing the file and checking it in is enough.

Before you add the tab in your selected team, you should first go in the SharePoint site behind that team to install the webpart similar to a normal SPFx webpart. This is a must at this point.

Once all the above have been correctly applied, you can now go and add your newly deployed tab in the team by clicking apps and then select “Built for {Tenant Name}”.

Updating Teams Webpart

Teams webpart, being like any other webpart, you can update your code as normally, just remember to change the version in the package-solution.json file and the manifest.json under the teams folder. Then you should go to the SharePoint site of the team and under Site Contents, fetch the new version of the webpart. This should update the teams tab as well.

Final Thoughts

This is my first blog post, so any feedback is greatly appreciated. Let me know if anything mentioned above was unclear. I will be sharing the webpart under github in the next few days.

Leave a Reply

Your email address will not be published. Required fields are marked *