Global Navigation and Branding for Modern Site using SharePoint Framework Extensions
Rate this post

Last month at the Microsoft Ignite 2017, SharePoint Framework Extensions became GA. It gave us whole new capabilities how we can customize Modern Team sites and Communication sites.
Even though there are lots of PnP examples on SPFx extensions, while presenting at Office 365 Bootcamp, Melbourne and taking a hands-on lab, I realised not many people are aware of the new capabilities that SPFx extensions provide. One of the burning question we often get from clients, if we can have a custom header, footer and global navigation in the modern sites and the answer is YES. Here is an example where Global Navigation has been derived from Managed Metadata:
Communication Site with header and footer:

Modern Team Site with header and footer (same navigation):

With the latest Yeoman SharePoint generator, along with the SPFx Web Part now we have options to create extensions:

To create header and footer for the modern site, we need to select the Application Customizer extension.
After the solution has been created, one noticeable difference is TenantGlobalNavBarApplicationCustomizer is extending from BaseApplicationCustomizer and not BaseClientSideWebPart.

export default class TenantGlobalNavBarApplicationCustomizer
extends BaseApplicationCustomizer

Basic Header and Footer

Now to create a very basic Application Customizer with header/footer, make sure to import the React, ReactDom, PlaceholderContent and PlaceholderName:

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

In the onInit() function, the top(header) and the bottom (footer) placeholders need to be created:

const topPlaceholder =  this.context.placeholderProvider.tryCreateContent(PlaceholderName.Top);
const bottomPlaceholder =  this.context.placeholderProvider.tryCreateContent(PlaceholderName.Bottom);

Create the appropriate elements for the header and footer:

const topElement =  React.createElement('h1', {}, 'This is Header');
const bottomElement =   React.createElement('h1', {}, 'This is Footer');

Those elements can be rendered within placeholder domElement:

ReactDom.render(topElement, topPlaceholder.domElement);
ReactDom.render(bottomElement, bottomPlaceholder.domElement);

If you now run the solution:

  • gulp serve –nobrowser
  • Copy the id from src\extensions\.manifest.json file e.g. “7650cbbb-688f-4c62-b5e3-5b3781413223”
  • Open a modern site and append the following URL (change the id as per your solution):
    ?loadSPFX=true&debugManifestsFile=https://localhost:4321/temp/manifests.js&customActions={“7650cbbb-688f-4c62-b5e3-5b3781413223”:{“location”:”ClientSideExtension.ApplicationCustomizer”}}

The above 6 lines code will give the following outcome:

Managed Metadata Navigation

Now back to the first example. That solution has been copied from SPFx Sample and has been updated.
To get the above header and footer:

Go to command line and run

  • npm i
  • gulp serve –nobrowser
  • To see the code running, go to the SharePoint Online Modern site and append the following with the site URL:

    ?loadSPFX=true&debugManifestsFile=https://localhost:4321/temp/manifests.js&customActions={“b1efedb9-b371-4f5c-a90f-3742d1842cf3”:{“location”:”ClientSideExtension.ApplicationCustomizer”,”properties”:{“TopMenuTermSet”:”TopNav”,”BottomMenuTermSet”:”Footer”}}}

Deployment

Create an Office 365 CDN
Update config\write-manifests.json file “cdnBasePath” to the new location. E.g.

"cdnBasePath":"https://publiccdn.sharepointonline.com/<YourTenantName>.sharepoint.com//<YourSiteName>//<YourLibName>/<FoldeNameifAny>"

In the command line, run

  • gulp bundle –ship
  • gulp package-solution –ship

and upload all artefacts from \temp\deploy\ to the CDN location
Upload \sharepoint\solution.sppkg to the App Library
Go to the Modern Site > Site Content > New > App > select and add the app:

Hopefully, this post has given an overview on how to implement SPFx Application Customizers. There are many samples available in the GitHub SharePoint.

Category:
Office 365, SharePoint, User Experience
Tags:
, ,

Leave a Reply

  Subscribe  
newest oldest most voted
Notify of
Prakash Acharya (@coresoul)
Guest

Hi Thank you so much for this article. Has this been tested in Modern team sites and communication sites? Is this a details info required to implement global nav across all site collections?

Saul
Guest
Saul

Any idea how to make the footer not to stick to the bottom of the page? Just have a regular end of page footer?

ricalski
Guest

It’s not showing up at all?
I used gulp serve –nobrowser and the CDN / app deployment similar to webparts
temp/deploy assets are in the cdn hosted in sharepoint like my other working webparts
app has been added and trusted in appcatalog like my other working webparts
i used the same url query and adjusted the quotations that were left / right double quotes on the page here with the customActions guid shown in the serve.json – customactions
my code is exactly the same within the OnInit override function…

Cyan007
Guest
Cyan007

You need to append a URL such as the following to the page you’re on (not within the workbench):
?loadSPFX=true&debugManifestsFile=https://localhost:4321/temp/manifests.js&customActions={“c5d41c05-99d1-459a-a9ab-c5d030dbd207”:{“location”:”ClientSideExtension.ApplicationCustomizer”}}
Then your extension will show up from gulp serve –nobrowser
customActions GUID is specific to your extension.

Adam Larner
Guest

Thanks for sharing this. But I’m guessing you need to apply this web part on every page within the site in order for the custom header/footer to be present throughout? Also, what stops the user from removing the web part and lose our company’s branding? We’re after a solution which would allow our users to have a seamless navigation between our publishing sites, team sites, modern team sites and communications sites. At the moment we can only do it on the classic type sites which is rather frustrating as it’s preventing us from rolling out the modern experience to our… Read more »

alan
Guest
alan

Hi, how can i modify the Office 365 top Navigation Menu, so I can add a custom logo?

Lucian Franghiu
Admin

Go to O365 Portal > Select Settings > Organisational Profile > Edit Theme
For more info: https://support.office.com/en-us/article/customize-the-office-365-theme-for-your-organization-8275da91-7a48-4591-94ab-3123a3f79530

Jesse
Guest
Jesse

How would one go about extending functionality of this to use the “split button” on elements with sub menus within the office ui fabric react contextual menu as you have implemented in your solution?
This would be useful in the case of using the heading of a submenu to as a link, and the expand button to expand the submenu. Hence a split button.
Unfortunately, just by adding ‘split: true’ within the projectMenuItem function within the TenantGlobalNavBar.tsx does not accomplish this.
Example of split button: https://developer.microsoft.com/en-us/fabric#/components/contextualmenu – “ContextualMenu with checkable menu items and toggable split button”
https://github.com/OfficeDev/office-ui-fabric-react/blob/master/packages/office-ui-fabric-react/src/components/ContextualMenu/examples/ContextualMenu.Checkmarks.Example.tsx

ynotlim
Guest

How did you get rid of the left side navigation on that first screen shot and put the search bar on the right? Can SPX accomplish that?

Jesse
Guest
Jesse

This is the layout for modern communication sites, where as the left side navigation is the layout within modern teams sites, or the view when within list/libraries.

ynotlim
Guest

How did you center the menu bar from the original source code from Microsoft? Changing the CSS file, i’m unable to center it. Thanks!!

Sean
Guest
Sean

Any chance you could shed some light on how you integrated the image into the global nav?

Krishna
Guest
Krishna

Can i Deploy my JS and Css files for branding the same way

Asfand
Guest

i would like to know how to hide left nav in SPFx using javascript.
right now i am able to do it by inject javascript in header with little setTimeOut
and for sure its not the best approach.

Sharanya
Guest
Sharanya

Adding sublevel removes the link of the parent level and converts it to button. For example if I am adding something under News, News is no longer a link it is a button to show its sub levels. Does it happens for you as well? If so how should we change the code to retain the parent link?

Follow Us!

Kloud Solutions Blog - Follow Us!