SPFx Application Customizer - An Analog Clock With REACT
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
- Run Windows PowerShell as administrator.
- Create a new project directory named “ReactAnalogExt” in your preferred location using the below command.
- md ReactAnalogExt
- cd ReactAnalogExt
- Create a new AppCustomizer extension by running the below command in the console.
- *yo @microsoft/sharepoint*
Provide required information when prompted
- Keep the default react-analog-ext for “What is your solution name?” and select "Enter".
- Keep SharePoint Online only (latest) for “Which baseline packages do you want to target for your component(s)?” and select Enter.
- Keep Use the current folder for “Where do you want to place the files?” and select Enter.
- Select No (N) to require tenant admin install extension on each site and press Enter. Here, make sure you select No (N). If you choose Yes (y), Elements.xml feature deployment file will not be generated through scaffolding.
- Choose Extension for “Which type of client-side component to create?” (Use arrow keys)
- Select Application Customizer as extension type from the list of available options.
As soon as you select Application Customizer, next, the group of prompts asks for information regarding your extension.
- Add ReactAnalog as your extension name, and press Enter.
- Keep the default ReactAnalogdescription for “What is your Application Customizer description?” and select Enter.
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.
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.
- Install by executing npm install react-clock
- Import by adding import Clock from 'react-clock'.
- Use by adding <Clock />.
Structure of the solution for Application Customizer
Debug Application Customizer
Local Workbench cannot be used to test SharePoint Framework Extensions. You can test the extension using the SharePoint Online site. However, you do not need to deploy your customization to the site.
Open up JSON file from inside the config folder. you will need to edit this file for debugging purpose. Edit pageURL (Current siteURL) for your tenant, which you need to utilize for testing purpose. https://www.c-sharpcorner.com/article/spfx-application-customizer-an-analog-clock-with-react/Images/SPFx%20Application%20Customizer%20-%20An%20Analog%20Clock%20With%20REACT4.png
serve.json
"$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
- Application Customizer extensions are supported with Site, Web, and List
- Open the ReactAnalogApplicationCustomizer.ts file in the src\extensions\reactAnalog\ReactAnalogApplicationCustomizer.ts
- It imports the base class BaseApplicationCustomizer for the App Customizer from sp-application-base package which contains SharePoint framework code.
- Add the PlaceholderContent and PlaceholderName to the import from @microsoft/sp-application-base by updating the import statement as follows,
import {
BaseApplicationCustomizer,
PlaceholderContent,
PlaceholderName
} from '@microsoft/sp-application-base';
Create the React Component for Analog Clock under Extension folder:
Create the tsx file under the src\extensions\reactAnalog\
In the below code Import reack-clock reference required
reactAnalog.tsx
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 : new Date()
}
}
startClock() {
setInterval(() => {
console.log("updating time")
this.setState({
currentTime: new Date()
})
}, 1000)
}
public render(): JSX.Element {
return (
<div className={styles.topclock}>
<Clock
value={this.state.currentTime}
/>
);
}
}
Branding
Under the src\extensions\reactAnalog folder, create a new file module.scssas as shown below.
Update module.scss with styles used in the HTML output for Analog Clock as well as header.
AppCustomizer.module.scss
.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.
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.
import reactAnalog, { IreactAnalogProps } from './reactAnalog';
Steps 3
Modify the IReactAnalogApplicationCustomizerProperties interface to add required properties for Header.
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.
/** 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.
@override
public onInit(): Promise<void> {
Log.info(LOG_SOURCE, `Initialized ${strings.Title}`);
this.context.placeholderProvider.changedEvent.add(this, this._renderPlaceHolders);
return Promise.resolve<void>();
}
Steps 6
Create a new _renderPlaceHolders private method with the following code.
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.
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,
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
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".
Final O/p