Hiding Approve/Reject button in SharePoint modern experience views using SharePoint Framework

As more and more organizations tend to use PowerAutomate approvals instead of SharePoint’s own approval workflow it becomes necessary to hide the Approve/Reject menu item in modern experience views to avoid confusing your end-users. Here’s a way to accomplish this using SharePoint Framework.

Using a SharePoint Framework Application Customizer you can easily insert the following code in your OnInit() method for injecting a style into the current page:

var style = document.createElement('style');
style.innerHTML =
  'button[name="Approve/Reject"] {' +
    'display: none;' +
  '}';
var ref = document.querySelector('script');
ref.parentNode.insertBefore(style, ref);

This hides the button element named “Approve/Reject” and works perfectly fine.

Drawback of this solution is that you directly manipulate the DOM and Microsoft doesn’t want you to do this for a good reason. The DOM of SharePoint and especially SharePoint Online pages often changes without prior notification and this can potentially break your implementation – maybe not this one because it only relies on the existence of the script tag and I guess this won’t vanish in future versions :-). Furthermore you wouldn’t be able to publish this implementation to Appsource because Microsoft doesn’t accept SharePoint Framework applications directly manipulating the DOM – see https://docs.microsoft.com/en-us/sharepoint/dev/spfx/publish-to-marketplace-checklist.

So how to come around this?

For DOM manipulation Microsoft provides an abstraction layer which encasulates the DOM elements which you implement against. For example for an Application Customizer like this you can refer to the Top and the Bottom placeholder on the current page. So I’m using the Top placeholder for injecting the style which is hiding the Approve/Reject element.

this._topPlaceholder.domElement.innerHTML = `<style>button[name="Approve/Reject"] {display: none;}</style>`;

See my complete hideApprovalControls\HideApprovalControlsApplicationCustomizer.ts to get an understanding how to use the placeholders.

import { override } from '@microsoft/decorators';
import { Log } from '@microsoft/sp-core-library';
import {
  BaseApplicationCustomizer,
  PlaceholderName,
  PlaceholderContent
} from '@microsoft/sp-application-base';
import { Dialog } from '@microsoft/sp-dialog';

import * as strings from 'HideApprovalControlsApplicationCustomizerStrings';

const LOG_SOURCE: string = 'HideApprovalControlsApplicationCustomizer';

export interface IHideApprovalControlsApplicationCustomizerProperties {
  debugMessage: string;
}

export default class HideApprovalControlsApplicationCustomizer
  extends BaseApplicationCustomizer<IHideApprovalControlsApplicationCustomizerProperties> {
  
  private _topPlaceholder: PlaceholderContent | undefined;

  @override
  public onInit(): Promise<void> {
    Log.info(LOG_SOURCE, `Initialized ${strings.Title}. Version is ${this.manifest.version}`);

    // Comment in for debugging.
    
    // let message: string = this.properties.debugMessage;
    // Dialog.alert(`Debug ${strings.Title}:\n\n${message}`);

    // Wait for the placeholders to be created (or handle them being changed) and then
    // render.
    this.context.placeholderProvider.changedEvent.add(this, this._renderPlaceHolders);

    return Promise.resolve();
  }

  private _renderPlaceHolders(): void {
    // Handling the top placeholder
    if (!this._topPlaceholder) {
      this._topPlaceholder = this.context.placeholderProvider.tryCreateContent(
        PlaceholderName.Top
      );
  
      // 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._topPlaceholder.domElement) {
        this._topPlaceholder.domElement.innerHTML = `<style>button[name="Approve/Reject"] {display: none;}</style>`;
      }
    }
  }
}

A detailed explanation how to use the placeholders you find in this document.

You can find the complete code in this GitHub repo.

If you are in a hurry you might just want to install the ready built SharePoint Framework package. It will load the JavaScript code from my CDN:

Be sure to hit Ctrl+F5 on your SharePoint view to reload the page from the server after installing the package.

Have fun.

Leave a Reply

Your email address will not be published. Required fields are marked *