Microsoft 365 Microsoft Graph

A Lap around Microsoft Graph Toolkit Day 13 – Using Microsoft Graph Toolkit with React

Author: Fabio Franzini, Microsoft Office Development and Microsoft Business Application MVP

@franzinifabioGitHub | LinkedIn 

Introduction 

Welcome to Day 13 of the Microsoft Graph Toolkit blog series! 

There are many application scenarios where developers need to create or modify stand-alone web applications using specific frameworks such as React – not just HTML or JavaScript. Microsoft itself uses this framework in many services and libraries among the most famous there is Fluent UI, a UI control library used in the Microsoft 365 services ecosystem and beyond. In this blog, we create a web application in React and show you how to use the Microsoft Graph Toolkit for both authentication and event visualization.   

Here is a preview of the web application

View of the React application that will be built

In making the application, we use two approaches. First, we integrate the MGT components directly with React and highlight everything needed to make things workThen, we use the MGT-React librarya set of React controls that wrap the MGT web component library. 

Creating Web App in React 

First, we create a web app in React. 

There are several ways to do this, but let’s make it easy by using a simple command called “create-react-app”. This command is extremely powerful because, thanks to the many options available, it is possible to do the scaffolding of the entire project with just a few manual operations.  And, by executing this command using “npx, we don’t need to worry about the version as it always runs the latest version available. 

npx create-react-app demo-mgt-react --template typescript

I added “–template typescript” as a parameter to use TypeScript as a programming language instead of the classic JavaScript. 

Now that we have created the project, we add the necessary npm library that is “@microsoft/mgt”: 

npm install @microsoft/mgt –save

Using MGT Providers 

To recover data, this application requires you to have a provider configured. In this example we’re using MsalProvider, but we could use any other provider provided by MGT, it depends on the context in which you have to use it. Inside the App.tsx file we are going to add the following code which (when using a valid Client-ID) allows you to set MsalProvider and use its status to check if the user is logged in or not. 

function App() { 
  const [isLoggedIn, setIsLoggedIn] = useState(false); 
  Providers.globalProvider = new MsalProvider({ clientId: '[CLIENT_ID]' }); 
  Providers.globalProvider.onStateChanged((e) => { 
    if (Providers.globalProvider.state !== ProviderState.Loading) 
      setIsLoggedIn(Providers.globalProvider.state === ProviderState.SignedIn); 
  }); 
  ... 
}

Using MGT Web Components in React 

React has a syntax called JSX (or TSX if we use TypeScript) which is slightly different than HTML. For this reason, TSX type markup (TypeScript) can’t understand non-“standard” tags associated with a web component.  

Let’s add this declaration to the index.tsx file: 

declare global { 
  namespace JSX { 
    interface IntrinsicElements { 
      'mgt-login': any; 
      'mgt-agenda': any; 
      'mgt-person': any; 
    } 
  } 
}

In this way, we can use these tags without problems in React. For new components, we can just add the syntax “'[COMPONENT NAME]’: any” inside IntrinsicElements interface. 

We can now focus on how to use MGT components in React. 

The first component we’ll use is the Login componentWe want to insert it into a new React navigation bar component which we’ll call NavBar. 

import React from 'react'; 
import '@microsoft/mgt'; 

const NavBar = () => { 
    return ( 
        <nav> 
            <mgt-login></mgt-login> 
        </nav> 
    ); 
} 

export default NavBar;

We are only using the “mgt-login” tag, with no attributes (which we could use). 

Let’s now configure the “mgt-agenda” component with a custom template to display the data contained in the user’s agenda. 

By defining the custom template for the component, we immediately face our first problem. Unfortunately, the syntax with braces “{” or “}” used in the MGT templating system conflicts with the same syntax as React. 

To solve this conflict, have two possible choices: 

  1. Modify the binding syntax used in MGT and you can do it simply like this:
    import { TemplateHelper } from '@microsoft/mgt'; 
    TemplateHelper.setBindingSyntax('[[', ']]');
  2. Use the “data-” attributes to drive the binding directly on the DOM elements, which is the approach we used in this case. 

In React, using the “ref” property it is possible to have a reference to the element that will be represented in the DOM of the page. In this way we can dynamically “hook” the object that will represent the context of the template. We are therefore able to pass to the template system the functions that are needed to format or do other things at the templating level. 

Here is an example of a custom template implementation for the mgt-agenda component taken from an earlier post in our seriesA Lap around Microsoft Graph Toolkit Day 5 – Customizing Components using Templates): 

import React, { useRef, useEffect } from 'react'; 
import '@microsoft/mgt'; 

const AgendaWC = () => { 
    const agendaRef = useRef<any>(null); 

    useEffect(() => { 
        agendaRef.current.templateContext = { 
            openWebLink: (e: any, context: { event: { webLink: string | undefined; }; }, root: any) => { 
                window.open(context.event.webLink, '_blank'); 
            }, 
            getDate: (dateString: string) => { 
                let dateObject = new Date(dateString); 
                return dateObject.setHours(0, 0, 0, 0); 
            }, 
            getTime: (dateString: string) => { 
                let dateObject = new Date(dateString); 
                return dateObject.getHours().toString().padStart(2, '0') + ':' + dateObject.getMinutes().toString().padStart(2, '0'); 
            } 
        } 
    }, []); 

    return ( 
        <mgt-agenda group-by-day ref={agendaRef}> 
            <template data-type="event"> 
                <div className="..."> 
                    <div className="..." 
                        data-props="{{@click: openWebLink, innerHTML: event.subject}}" /> 
                    <div className="..." data-if="getDate(event.start.dateTime) == getDate(event.end.dateTime)" 
                        data-props="{{innerHTML: 'from ' + getTime(event.start.dateTime) + ' to ' + getTime(event.end.dateTime)}}" /> 
                    <div className="..." data-if="event.body.content != ''" 
                        data-props="{{innerHTML: event.body.content}}" /> 
                </div> 
            </template> 
            <template data-type="no-data"> 
                <div className="..."> 
                    No events to show 
              </div> 
            </template> 
        </mgt-agenda> 
    ); 
} 

export default AgendaWC;

Now we can use the two React components inside the main component called “App”. This is the final result: 

import React, { useState } from 'react'; 
import { Providers, MsalProvider, ProviderState } from '@microsoft/mgt'; 
import NavBar from './navBar' 
import AgendaWC from './agendaWC' 
 
function App() { 
  const [isLoggedIn, setIsLoggedIn] = useState(false); 
  Providers.globalProvider = new MsalProvider({ clientId: [CLIENT_ID]' }); 
  Providers.globalProvider.onStateChanged((e) => { 
    if (Providers.globalProvider.state !== ProviderState.Loading) 
      setIsLoggedIn(Providers.globalProvider.state === ProviderState.SignedIn); 
  }); 
 
  return ( 
    <div> 
      <NavBar /> 
      {(isLoggedIn) ? 
        <div className="..."> 
          <div> 
            <h1 className="..."> 
              Agenda 
            </h1> 
            <AgendaWC /> 
          </div> 
        </div> 
        : 
        <div className="..."> 
          Login to show data 
        </div> 
      } 
    </div> 
  ); 
} 
 
export default App;

Using MGT with “mgt-react”

A more elegant way of integrating MGT with React is to use the mgt-react library. This is a library of React components that wraps all MGT components. Let’s see how it is used. 

First, we need to add the npm package: 

npm install mgt-react -–save

 Then we import the components (React) that we want to use: 

import { Agenda, MgtTemplateProps } from 'mgt-react';

All the attributes and events of the MGT component are mapped as properties of the corresponding React component, very simple. 

For the templating part, however, everything changes. We can use all the power and knowledge in React to define the template with the syntax and components in React! 

We can define a React component that has the MgtTemplateProps object as its type of props, like this: 

import { MgtTemplateProps } from 'mgt-react'; 

const MyEvent = (props: MgtTemplateProps) => { 
  const { event } = props.dataContext; 
  return <div>{event.subject}</div>; 
};

And use it in the component (always React) Agenda like this: 

import { Agenda } from 'mgt-react'; 
 
const App = (props) => { 
  return <Agenda> 
    <MyEvent template="event"> 
  </Agenda> 
}

The “template” property (defined into the ”MgtTemplateProps” type) is used to understand which template (available in the Agenda control) is associated with the MyEvent control. 

In this case, there is no need to use the ref property to “hook” the context of the template with custom functions. Simply create the functions you need in the component that acts as a template. 

Let’s now implement the same template as before with the new set of React controls: 

import React from 'react'; 
import '@microsoft/mgt'; 
import { Agenda, MgtTemplateProps } from 'mgt-react'; 
 
const AgendaReact = () => { 
    return ( 
        <Agenda groupByDay={true} > 
            <Event template="event" /> 
            <NoData template="no-data" /> 
        </Agenda> 
    ); 
} 
 
const Event = (props: MgtTemplateProps) => { 
    const { event } = props.dataContext; 
    const openWebLink = () => { 
        window.open(event.webLink, '_blank'); 
    }; 
 
    const getDate = (dateString: string) => { 
        let dateObject = new Date(dateString); 
        return dateObject.setHours(0, 0, 0, 0); 
    }; 
 
    const getTime = (dateString: string) => { 
        let dateObject = new Date(dateString); 
        return dateObject.getHours().toString().padStart(2, '0') 
            + ':' + 
            dateObject.getMinutes().toString().padStart(2, '0'); 
    }; 
 
    return ( 
        <div className="..."> 
            <div className="..." onClick={() => { openWebLink(); }}> 
                {event.subject} 
            </div> 
            {(getDate(event.start.dateTime) 
                == getDate(event.end.dateTime)) ? 
                <div className="..."> 
                    from {getTime(event.start.dateTime)} 
                    to {getTime(event.end.dateTime)} 
                </div> 
                : null 
            } 
            {(event.body.content != '') ? 
                <div className="..." 
                    dangerouslySetInnerHTML={{ __html: event.body.content }} /> 
                : null 
            } 
        </div> 
    ); 
}; 
 
const NoData = (props: MgtTemplateProps) => { 
    return <div className="..."> 
        No events to show 
      </div> 
}; 
 
export default AgendaReact;

Add a style to this React App 

Obviously, what is missing is a bit of style. MGT components already have their own style, but when we go to define our templates, we must make do with the CSS we want to use. In this example application I used a very interesting CSS framework, Tailwind CSS, added as a regular npm package: 

npm install tailwindcss -–save

As for Tailwind CSS, the only thing we need to do before using it in the project is to create a file like “tailwind.css” in the root of the “src” folder and add this content: 

@tailwind base; 
@tailwind components; 
@tailwind utilities;

This is used by the Tailwind CSS compiler to generate the CSS that will contain the classes used. 

Now the only thing to do is to use the classes that the framework makes available to give style to the application. I leave you at the official link to learn more about Tailwind CSS here: https://tailwindcss.com/. 

Recap 

We have come to an end and we have managed to use MGT within a React application. 

We have learned how we can: 

  • use directly the MGT components in React 
  • define any templates using the syntax that MGT makes available 
  • use the “mgt-react” library to simplify the use of MGT components with React 

You can find the source code for this React App sample here: https://github.com/microsoftgraph/mgtLap-TryItOut 

filter-icon