Introduction

 
In this article, we will explore how to show the React Analog Clock in SharePoint Framework. We will use the Application Customizer extension to show an analog clock in header placeholder.
 

Create an extension project

Provide required information when prompted

As soon as you select Application Customizer, next, the group of prompts asks for information regarding your extension.
SPFx Application Customizer - An Analog Clock With REACT 
 
Yeoman installs the needed dependencies and scaffolds the solution files along with the AppCustomizer extension. This may take some time to install the dependencies files.
 
When scaffolding is done, you will get a successful scaffold message. After a successful scaffold, the below message appears.
 
SPFx Application Customizer - An Analog Clock With REACT 
 
To start, open the solution in Visual Studio Code and type the following command.
 
Code .
 

React-analog Clock(npm Packages)

 
Add React-Clock to Application Customizer extension. The below points are required.

Structure of the solution for Application Customizer

 
SPFx Application Customizer - An Analog Clock With REACT

 

JavaScript
Edit|Remove
"$schema""https://developer.microsoft.com/json-schemas/core-build/serve.schema.json",   
  "port"4321,   
"https": true,   
 "serveConfigurations"{"default"{"pageUrl""https://Domain-name/sites/Demo/SitePages/Home.aspx",   
      "customActions"{"99481ef9-1a6b-492c-88e7-fc8831e81fc1"{"location""ClientSideExtension.ApplicationCustomizer",   
          "properties"{"testMessage""Test message"}}}},   
    "reactAnalog"{"pageUrl""https:// Domain-name/sites/Demo/SitePages/Home.aspx",   
      "customActions"{"99481ef9-1a6b-492c-88e7-fc8831e81fc1"{"location""ClientSideExtension.ApplicationCustomizer",   
          "properties"{"testMessage""Test message"}}}}}}

 

Implement the Application Customizer

JavaScript
Edit|Remove
import {   
    BaseApplicationCustomizer,   
    PlaceholderContent,   
    PlaceholderName   
} fr
 

 

JavaScript
Edit|Remove
import * as React from 'react';   
import Clock from 'react-clock';   
import styles from './AppCustomizer.module.scss';   
export interface IreactAnalogProps {}   
export interface IreactAnalogPropsoState {   
    currentTime: Date;   
}   
export default class reactAnalog extends React.Component<IreactAnalogProps,IreactAnalogPropsoState> {   
    constructor(props: IreactAnalogProps) {   
        super(props)   
       this.startClock()   
        this.state = {   
         currentTime : newDate()   
      }}   
     startClock() {   
        setInterval(() => {   
         console.log("updating time")   
         this.setState({   
           currentTime: newDate()   
        })   
      }1000)   
    }   
  public render(): JSX.Element {return (   
  <div className={styles.topclock}>   
     
   <Clock    
     value={this.state.currentTime}    
 />       
  );   
 }}

 

CSS
Edit|Remove
.rectapp{   
   
  .topclock{   
  height: 0px !important;   
  margin-left:550px!important;   
  margin-top:40px!important;   
  }   
  .topclock time{   
  width: 96px!important;   
  height: 92px!important;   
  margin-top: -36px!important;   
  margin-bottom: 563PX!important;   
  }   
}  
 

ReactAnalogApplicationCustomizer.ts

 
Open src\extensions\appCustomizer\ReactAnalogApplicationCustomizer.ts in the code editor and import at the top, add the below import statements step by step.
 
Steps 1
 
Import React,ReactDOM,PlaceholderContent and PlaceholderName from @microsoft/sp-application-base library.
JavaScript
Edit|Remove
import { override } from '@microsoft/decorators';   
import { Log } from '@microsoft/sp-core-library';   
import * as React from 'react';   
import * as ReactDOM from "react-dom";    
import {   
  BaseApplicationCustomizer,   
  PlaceholderContent,   
  PlaceholderName   
} from '@microsoft/sp-application-base'
 
Steps 2
 
Import the React component by using the below line.
JavaScript
Edit|Remove
import reactAnalog, { IreactAnalogProps } from './reactAnalog';  
 
Steps 3 
 
Modify the IReactAnalogApplicationCustomizerProperties interface to add required properties for Header.
JavaScript
Edit|Remove
export interface IReactAnalogApplicationCustomizerProperties {   
  // This is an example; replace with your own property   
  Top: string;   
}  
 
Steps 4
 
Add the below private variables. In this case, variables can be defined locally in the onRender method, though if you need to share them with other objects, define the variables as private.
JavaScript
Edit|Remove
/** A Custom Action which can be run during the execution of a Client-Side Application */   
export default class ReactAnalogApplicationCustomizer   
  extends BaseApplicationCustomizer<IReactAnalogApplicationCustomizerProperties> {   
    private _topPlaceholder: PlaceholderContent | undefined;
 
Steps 5
 
Update the onInit method code as below.
JavaScript
Edit|Remove
@override   
  public onInit(): Promise<void{   
    Log.info(LOG_SOURCE, `Initialized ${strings.Title}`);   
   
       this.context.placeholderProvider.changedEvent.add(thisthis._renderPlaceHolders);   
     
    return Promise.resolve<void>();   
  }  
 
Steps 6
 
Create a new _renderPlaceHolders private method with the following code.
JavaScript
Edit|Remove
private _renderPlaceHolders(): void {   
    console.log("HelloWorldApplicationCustomizer._renderPlaceHolders()");   
    console.log(   
      "Available placeholders: ",   
      this.context.placeholderProvider.placeholderNames   
        .map(name => PlaceholderName[name])   
        .join(", ")   
    );   
    // Handling the top placeholder   
    if (!this._topPlaceholder)    
    {   
      this._topPlaceholder = this.context.placeholderProvider.tryCreateContent(   
        PlaceholderName.Top,   
        { onDispose: this._onDispose }   
      );   
 // The extension should not assume that the expected placeholder is available.   
      if (!this._topPlaceholder)    
      {   
        console.error("The expected placeholder (Top) was not found.");   
        return;   
      }   
      if (this.properties) {   
        let topString: string = this.properties.Top;   
        if (!topString) {   
          topString = "(Top property was not defined.)";   
        }   
          if (this._topPlaceholder.domElement) {   
        const elem: React.ReactElement<IreactAnalogProps> = React.createElement(   
          reactAnalog,{});   
         ReactDOM.render(elem, this._topPlaceholder.domElement);    
        }        
     }   
    }   
  }  
 
Steps 7
 
Add _onDispose method as shown below after completion of _renderPlaceHolders method. You can output the below console message on the removal of extension from the page.
JavaScript
Edit|Remove
private _onDispose(): void    
  {   
    console.log('[ReactAnalogApplicationCustomizer._onDispose] Disposed custom top and bottom placeholders.');   
  } 
 

Now ready to test the customizer in SharePoint Online 

 
Go Open the Visual code ->Terminal Tab->New terminal,
  1. Developer certificate has to be installed ONLY once in your development environment, so you can skip this step if you have already executed that in your environment.

    gulp trust-dev-cert
  1. Compile your code and host the compiled files from your local computer by running the following command,

    gulp serve
To continue loading scripts from localhost, click "Load debug scripts".
 
SPFx Application Customizer - An Analog Clock With REACT
 

Final O/p

 
SPFx Application Customizer - An Analog Clock With REACT