In this SPFx development tutorial, we will discuss an SPFx Application Customizer Example on how to show an analog clock using SPFx application customizer with React. Here we will display the Analog Clock in header placeholder using SPFx Application Customizer extension.
SPFx Application Customizer Example
First, we will create an SPFx extension project by following the below steps:
Run Windows PowerShell as an 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), the 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 an 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 the project using visual studio code, open the solution in Visual Studio Code and type the following command.
Code .
React-analog Clock(npm Packages)
First, we need to add React-Clock to Application Customizer extension. Follow the below command to install React-analog Clock
- Install by executing npm install react-clock
- Import by adding import Clock from ‘react-clock’.
- Use by adding <Clock/>
The structure of the solution for SPFx Application Customizer looks like below:
Debug SPFx Application Customizer
Without deploying the SPFx application customizer to the SharePoint Online site, we can debug and test SharePoint Framework Extensions using the local workbench.
Open up the JSON file from inside the config folder. you will need to edit this file for debugging purposes. Edit pageURL (Current siteURL) for your tenant, which you need to utilize for testing purposes.
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 SharePoint 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 the 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.
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';
Import the React component by using the below line.
import reactAnalog, { IreactAnalogProps } from './reactAnalog';
Modify the IReactAnalogApplicationCustomizerProperties interface to add required properties for Header.
export interface IReactAnalogApplicationCustomizerProperties {
// This is an example; replace with your own property
Top: string;
}
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;
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>();
}
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);
}
}
}
}
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 Studio 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
You may like the following SharePoint framework tutorials:
- Setup SharePoint Framework (SPFx) development environment in Windows 10 workstation
- SharePoint client-side web part configurable properties in Property Pane using spfx
- Retrieve SharePoint list items using SharePoint framework (SPFx)
- How to get user details using Microsoft Graph API in SPFx
- Error TS2307 Cannot find module @pnp/sp/presets/all in SPFx
In this SPFx tutorial, we learned how to display an analog clock using the SPFx application customizer with React.
I am Developer working on Microsoft Technologies for the past 6+years. I am very much passionate about programming and my core skills are SharePoint, ASP.NET & C#,Jquery,Javascript,REST. I am running this blog to share my experience & learning with the community I am an MCP, MCTS .NET & Sharepoint 2010, MCPD Sharepoint 2010, and MCSD HTML 5,Sharepoint 2013 Core
Solutions. I am currently working on Sharepoint 2010, MOSS 2007, Sharepoint 2013,Sharepoint 2013 App Dev, C#, ASP.NET, and SQL Server 2008.