Creating a Custom Top Navigation Menu in SPFx with Application Customizer

In this technical article, we explore how to implement a custom top navigation menu in SharePoint Online using an SPFx Application Customizer. The code provided demonstrates how to inject a React component into the Top placeholder of a modern SharePoint page using the SPFx extension model.

This approach is useful for organizations that want to extend SharePoint’s out-of-the-box navigation without using classic methods or altering master pages.


Technical Overview

1. Imports and Dependencies

import * as ReactDOM from 'react-dom';
import * as React from 'react';
import { Log } from '@microsoft/sp-core-library';
import {
  BaseApplicationCustomizer,
  PlaceholderContent,
  PlaceholderName
} from '@microsoft/sp-application-base';

import NavigationMenu from './NavigationMenu';
import * as strings from 'TopMenuApplicationCustomizerStrings';

  • React & ReactDOM: Used to render the navigation menu as a React component.
  • BaseApplicationCustomizer: The base class for creating SharePoint extensions that customize placeholders.
  • PlaceholderContent & PlaceholderName: Used to manage rendering in the predefined Top and Bottom regions of the page.
  • NavigationMenu: The React component that will be injected into the placeholder.
  • strings: Localization strings for the extension (can be customized per language).

2. Extension Properties Interface

export interface ITopMenuApplicationCustomizerProperties {
  // This is an example; replace with your own property
}

  • This is a placeholder for passing configuration via ClientSideComponentProperties. It is not used in this example but can be extended to support dynamic configuration.

3. Class Declaration and Initialization

export default class TopMenuApplicationCustomizer
  extends BaseApplicationCustomizer<ITopMenuApplicationCustomizerProperties> {

The class TopMenuApplicationCustomizer extends BaseApplicationCustomizer, meaning it will be executed when SharePoint initializes the client-side application.

private _topPlaceholder: PlaceholderContent | undefined;

This private variable is used to ensure the navigation is only rendered once.

public async onInit(): Promise<void> {
  Log.info(LOG_SOURCE, `Initialized ${strings.Title}`);
  this.context.placeholderProvider.changedEvent.add(this, this._renderPlaceHolders);
  return Promise.resolve();
}

  • onInit(): Subscribes to the changedEvent of the placeholderProvider, which triggers when placeholders become available on the page.
  • It then calls _renderPlaceHolders() to render the top navigation.

4. Rendering the Placeholder

private _renderPlaceHolders(): void {

This method checks for available placeholders and renders the navigation component if the Top placeholder is available.

this._topPlaceholder = this.context.placeholderProvider.tryCreateContent(
  PlaceholderName.Top,
  { onDispose: this._onDispose }
);

  • tryCreateContent() attempts to create a content region in the top placeholder.
  • If successful, it renders the NavigationMenu React component:
const reactElt: React.ReactElement = React.createElement(
  NavigationMenu,
  {
    type: "Default",
    ListTitle: "TopMenu",
    AppContext: this.context,
    siteUrl: "https://sharepoint.com/sites/site"
  }
);
ReactDOM.render(reactElt, this._topPlaceholder.domElement);

This code dynamically injects the navigation menu using values such as the list title and site URL as props.


5. Cleanup Logic

private _onDispose(): void {
  console.log('[HelloWorldApplicationCustomizer._onDispose] Disposed custom top and bottom placeholders.');
}

This function is called when the placeholder content is removed, ensuring memory is properly managed.


Use Cases

  • Enterprise-wide top navigation menus.
  • Context-aware navigation based on site or user role.
  • Integration with SharePoint lists or external APIs to dynamically build menus.

Summary Table

SectionPurpose
BaseApplicationCustomizerBase class for SPFx Application Customizer extensions
placeholderProviderProvides hooks into the page’s placeholder locations
NavigationMenuReact component injected into the top placeholder
tryCreateContent()Safely attempts to use a placeholder (like Top or Bottom)
React.createElement()Creates the navigation component to render
ReactDOM.render()Injects the component into the page DOM
onDispose()Cleanup logic to avoid memory leaks
onInit()Entry point that sets up placeholder change detection

References

Edvaldo Guimrães Filho Avatar

Published by