Expand Minimize
This documentation is part of the BETA release and subject to change.

Don't manipulate DOM elements outside the component

You should not manipulate DOM elements outside your component, as SharePoint DOM can change breaking your customization

CheckId SPF050802
TypeName DontManipulateDomElementsOutsideComponent
Severity CriticalWarning
Type JavaScriptFile

When building SharePoint Framework solutions, you should avoid manipulating the DOM outside the component. SharePoint DOM should not be treated as an API and changes regularly. When it does, it breaks your solution that relies on the specific DOM structure of the page.

When building SharePoint Framework client-side web parts your solution should work with the domElement assigned to the web part:

// ...

export default class HelloWorldWebPart extends BaseClientSideWebPart<IHelloWorldWebPartProps> {

  public render(): void {
    this.domElement.innerHTML = `
      <div class="${styles.helloWorld}">
        <div class="${styles.container}">
          <div class="ms-Grid-row ms-bgColor-themeDark ms-fontColor-white ${styles.row}">
            <div class="ms-Grid-col ms-u-lg10 ms-u-xl8 ms-u-xlPush2 ms-u-lgPush1">
              <span class="ms-font-xl ms-fontColor-white">Welcome to SharePoint!</span>
              <p class="ms-font-l ms-fontColor-white">Customize SharePoint experiences using Web Parts.</p>
              <p class="ms-font-l ms-fontColor-white">${escape(this.properties.description)}</p>
              <a href="https://aka.ms/spfx" class="${styles.button}">
                <span class="${styles.label}">Learn more</span>
              </a>
            </div>
          </div>
        </div>
      </div>`;
  }
  // ...
}


When using jQuery, you should scope its queries to select elements only within the domElement:

// ...

export default class WeatherWebPart extends BaseClientSideWebPart<IWeatherWebPartProps> {
  private container: JQuery;

  public render(): void {
    if (this.renderedOnce === false) {
      this.domElement.innerHTML = `<div class="${styles.weather}"></div>`;
    }

    this.container = jQuery(`.${styles.weather}`, this.domElement);

    // ...
  }
  // ...
}


When building field customizers, you should work with the DIV assigned to the cell of the associated field:

// ...

export default class HelloWorldFieldCustomizer
  extends BaseFieldCustomizer<IHelloWorldProperties> {
  // ...

  @override
  public onRenderCell(event: IFieldCustomizerCellEventParameters): void {
    const text: string = '[' + CellFormatter.renderAsText(this.context.column, event.cellValue) + ']';

    event.cellDiv.innerText = text;

    event.cellDiv.classList.add(styles.cell);
  }

  // ...
}


In application customizers you can add markup to the DOM using known placeholders:

import {
  Placeholder
} from '@microsoft/sp-application-base';

// ...

export default class HelloWorldApplicationCustomizer
  extends BaseApplicationCustomizer<IHelloWorldApplicationCustomizerProperties> {
  // ...

  @override
  public onRender(): void {
    const headerPlaceholder: Placeholder = this.context.placeholders.tryAttach(
      'PageHeader',
      {
        onDispose: this.onDispose
      });

    if (headerPlaceholder) {
      headerPlaceholder.domElement.innerHTML = `
        <div class="${styles.app}">
          <div class="ms-bgColor-themeDark ms-fontColor-white ${styles.header}">
            <i class="ms-Icon ms-Icon--Info" aria-hidden="true"></i> ${escape(this.properties.header)}
          </div>
        </div>`;
    }
  }

  private onDispose(): void {
  }
}

Disclaimer: The views and opinions expressed in this documentation and in SPCAF do not necessarily reflect the opinions and recommendations of Microsoft or any member of Microsoft. SPCAF and RENCORE are registered trademarks of Rencore. All other trademarks, service marks, collective marks, copyrights, registered names, and marks used or cited by this documentation are the property of their respective owners.