How to Implement Custom UI Changes in SharePoint Online Using SPFx Extension

Introduction

 
Before we get started, if you are new to SharePoint Framework, please take a look at below articles about building SharePoint Framework webparts and extensions using the below links:
SharePoint Framework are extensions of the type Application.Customizer, which helps to perform JavaScript actions. By default, we have placeholders to render Headers and Footers in the SharePoint modern page.
 

SPFx Breadcrumb Workaround

 
Here we are going to use the same concept to implement BreadCrumb as well. But we don’t have default placeholder to get this done. We are going to see a workaround to implement breadcrumb in the SharePoint modern page under the Site Title. In short, we are going to do the below steps:
  • Identify the Site Title element using any of the JavaScript element selectors like ID, ClassName, TagName, AttributeName.
  • Create a new element for BreadCrumb in the DOM.
  • Append the new element next to the Site Title element.

Risks Involved

 
Since we are using our own workaround, there are risks involved in this approach. If Microsoft updated the Site Title section and removed/renamed any of the selectors that we use to identify the Site Title element, our approach will fail here.
 
But Site Title is an area that is stable for years, so it won’t be updated often. When you choose to do these types of customizations, you need to be clever and find the element to handle worst-case scenarios.
 

Implementation

 
Step 1
 
Create a new application as SPFx Extension Application.Customizer.
 
Step 2
 
Create a React Component for BreadCrumb using the OfficeUI Fabric component.
 
In Office UI Fabric, we have a component for breadcrumb. Let’s use that by importing the reference, like below:
  1. import { Breadcrumb, IBreadcrumbItem } from 'office-ui-fabric-react/lib/Breadcrumb';  
Check out the available properties of the component in the official documentation for Office UI Fabric breadcrumb and generate your breadcrumb.
 
Below is how the render method of this component will look:
  1. public render() {  
  2.     return (  
  3.       <Breadcrumb items={this.props.items} />);  
  4.   }  
Step 3
 
Go to the typescript file generated in the name of your extension. Below is the location of the typescript file:
  1. src/extensions/{YourExtensionName}/{YourExtensionName} ApplicationCustomizer.ts  
Step 4
 
Look for the onInit() method in the typescript file and replace the code in that with the following:
  1. this.context.placeholderProvider.changedEvent.add(thisPage, this.processBreadCrumb.bind(this));  
  2. this.context.application.navigatedEvent.add(thisPage, this.processBreadCrumb.bind(this));  
Here, we are adding our event handler method to the PlaceholderChangedEvent and ApplicationNavigated Event
 
PlaceholderChangedEvent – It will be triggered when the list of currently available placeholders is changed.
ApplicationNavigatedEvent – It will be triggered when the application's top-level page context navigates to a new page. In SharePoint online, redirection between pages sometimes happen with a soft refresh. In that case, we need to make sure that our breadcrumb is processed and displayed, so we need to register our handler method to this event also.
 
Step 5
 
Let’s implement our event handler method like below. Please take a look at the comments for each section in the code which helps you to understand the implementation better:
  1. private processBreadCrumb() {  
  2.         //Find if any existing element with same name and remvoe it, this will help if events triggered multiple times  
  3.         let breadCrumbDiv = document.getElementById("siteBreadCrumb");  
  4.         if (!this.isObjNull(breadCrumbDiv)) {  
  5.             breadCrumbDiv.remove();  
  6.             breadCrumbDiv = null;  
  7.         }  
  8.         //creating a div to inject breadcrumb  
  9.         breadCrumbDiv = document.createElement("div");  
  10.         breadCrumbDiv.setAttribute("id""siteBreadCrumb");  
  11.   
  12.         //Identify the SiteTitle using the query selector  
  13.         let titleElement = document.querySelector('[data-automationid="SiteHeaderTitle"]');  
  14.   
  15.         if (!this.isObjNull(titleElement)){  
  16.             //This helps to place our custom breadcrumb div element right below the Site Title  
  17.             let siteTitleParentParent = titleElement.parentElement.parentElement;  
  18.             siteTitleParentParent.insertBefore(breadCrumbDiv, titleElement.parentElement.nextSibling);  
  19.   
  20.             //Create a ReactElement using the BreadCrumbComponent which we create and render it inside the custom breadcrumbdiv  
  21.             const element: React.ReactElement<IBreadCrumdProps> = React.createElement(BreadCrumbComponent,  
  22.                 {  
  23.                     items: this.items  
  24.                 });  
  25.   
  26.             ReactDOM.render(element, breadCrumbDiv);  
  27.         }  
  28.     }  

Conclusion

 
I hope this article helps you to get an understanding of how to customize the SharePoint Online site to implement Breadcrumbs. If you have any questions/issues about this article, please let me know in the comments.