Customizing the SharePoint ribbon is not that easy it could be, when we need to package our customizations for deployments in any environment. But with the Office 365 PnP PowerShell extensions we have tools to make life a litte easier.

What I am struggling with often, is debugging the code for the CommandAction or the EnabledScript attributes in a CommandUIHandler. But there is an easy technique to extract the script from the ribbon definition (the CommandUIExtension). In this example a simple button should be added to the ribbon for elements of the content type “Document” (0x0101). When the user clicks the button in the ribbon we just show a simple dialog with the ID of the document.

The xml for the button is as follows:

		<CommandUIDefinition Location="Ribbon.Library.ViewFormat.Controls._children">
			<Button Id="Ribbon.Library.ViewFormat.About"
                TemplateAlias="o1" />
			EnabledScript="javascript:onlyOneItemSelected();" />

As we see in the CommandUIHandler, the CommandAction and the EnabledScript just contain calls to a JavaScript-function. These functions are placed in a simple JavaScript file:

function aboutScript(itemId) {
	alert("Hello user! You have selected item " + itemId);

function onlyOneItemSelected() {
	return (SP.ListOperation.Selection.getSelectedItems().length == 1)

To make this code available, we will store the file with the JavaScript-code in a document library in our SharePoint site. In the example, I prepared a library “Scripts” to store the file.

Now we can store the script file in the library, add the extension to the ribbon and make the file available for the ribbon extension. This could be done with the Office 365 PnP PowerShell extensions:

Add-PnPFile -Path .\AboutButtonScript.js -Folder "Scripts"

$ribbon = Get-Content .\MyRibbon.xml
$ribbon = [string]$ribbon
Add-PnPCustomAction -Name "RibbonTester" -Title "RibbonTester" -Description "-" -Group "Tester" -Location "CommandUI.Ribbon" -CommandUIExtension $ribbon -RegistrationType ContentType -RegistrationId 0x0101

Add-PnPJavaScriptLink -Name "AboutButtonScript" -Url -Scope Web

The result will look like this:

When we select a document in the library and click the button, the dialog will show the ID of the selected document.

Important: In our JavaScript file we cannot use the substation tokens, as it is shown in the CommandUIHandler Element description in MSDN. But as we have seen in the MyRibbon.xml example, we can use these tokens as parameters.

With the JavaScript code outside the CommandUIExtension, it is now very easy to develop and debug the code, because all we need to do is working the the script file that is stored in the library. Another advantage of this approach: we can reuse code for several implementations.