Migrieren von UserCustomAction zu SharePoint-Framework-Erweiterungen

Viele Unternehmenslösungen, die auf Microsoft 365 und SharePoint Online basieren, nutzten die CustomAction-Websitefunktion des SharePoint Feature Frameworks, um die Benutzeroberfläche von Seiten zu erweitern. In der aktuellen "modernen" Benutzeroberfläche von SharePoint Server 2019 und SharePoint Online sind die meisten dieser Anpassungen nicht mehr verfügbar. Glücklicherweise können Sie mit SharePoint-Framework Erweiterungen ähnliche Funktionen auf der "modernen" Benutzeroberfläche bereitstellen.

In diesem Lernprogramm erfahren Sie, wie Sie die alten, klassischen Anpassungen zu dem neuen Modell basierend auf SharePoint-Framework-Erweiterungen migrieren können.

Bei der Entwicklung von SharePoint-Framework-Erweiterungen sind folgende Optionen verfügbar:

  • Application Customizer: Erweitert die native „moderne“ Benutzeroberfläche von SharePoint, indem benutzerdefinierte HTML-Elemente und clientseitiger Code den vordefinierten Platzhaltern der „modernen“ Seiten hinzugefügt werden. Weitere Informationen zu Anwendungsanpassungen finden Sie unter Erstellen Ihrer ersten SharePoint-Framework-Erweiterung (Hello World, Teil 1).
  • Command Set: Fügt benutzerdefinierte ECB-Menüelemente (Edit Control Block) oder benutzerdefinierte Schaltflächen zur Befehlsleiste einer Listenansicht für eine Liste oder Bibliothek hinzu. Sie können diesen Befehlen eine beliebige clientseitige Aktion zuordnen. Weitere Informationen zu Befehlssätzen finden Sie unter Erstellen Ihrer ersten Erweiterung des Typs „ListView Command Set“.
  • Field Customizer: Passt das Rendering eines Felds in einer Listenansicht mit benutzerdefinierten HTML-Elementen und clientseitigem Code an. Weitere Informationen zu Feldanpassungen finden Sie unter Erstellen Ihrer ersten Field Customizer-Erweiterung.

Die nützlichste Option in diesem Kontext ist die Application Customizer-Erweiterung.

Angenommen, Sie verfügen über eine CustomAction in SharePoint Online, um eine benutzerdefinierte Fußzeile auf allen Seiten der Website zu haben.

Im folgenden Codeausschnitt ist der XML-Code enthalten, der CustomAction mithilfe des SharePoint-Feature-Frameworks definiert.

<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <CustomAction Id="jQueryCDN"
                Title="jQueryCDN"
                Description="Loads jQuery from the public CDN"
                ScriptSrc="https://code.jquery.com/jquery-3.2.1.slim.min.js"
                Location="ScriptLink"
                Sequence="100" />
  <CustomAction Id="spoCustomBar"
                Title="spoCustomBar"
                Description="Loads a script to rendere a custom footer"
                Location="ScriptLink"
                ScriptSrc="SiteAssets/SPOCustomUI.js"
                Sequence="200" />
</Elements>

Wie Sie sehen können, definiert die Datei mit den Feature-Elementen einige Elemente vom Typ CustomAction, die in den Seiten der Zielwebsite enthalten sind. Diese umfassen die über das öffentliche CDN geladene jQuery und eine benutzerdefinierte JavaScript-Datei, die die benutzerdefinierte Fußzeile rendert.

Der Vollständigkeit halber finden Sie den JavaScript-Code, der eine benutzerdefinierte Fußzeile rendert, deren Menüelemente der Einfachheit halber im Code vordefiniert sind.

var SPOCustomUI = SPOCustomUI || {};

SPOCustomUI.setUpCustomFooter = function () {
  if ($("#SPOCustomFooter").length)
    return;

  var footerContainer = $("<div>");
  footerContainer.attr("id", "SPOCustomFooter");

  footerContainer.append("<ul>");

  $("#s4-workspace").append(footerContainer);
}

SPOCustomUI.addCustomFooterText = function (id, text) {
  if ($("#" + id).length)
    return;

  var customElement = $("<div>");
  customElement.attr("id", id);
  customElement.html(text);

  $("#SPOCustomFooter > ul").before(customElement);

  return customElement;
}

SPOCustomUI.addCustomFooterLink = function (id, text, url) {
  if ($("#" + id).length)
    return;

  var customElement = $("<a>");
  customElement.attr("id", id);
  customElement.attr("href", url);
  customElement.html(text);

  $("#SPOCustomFooter > ul").append($("<li>").append(customElement));

  return customElement;
}

SPOCustomUI.loadCSS = function (url) {
  var head = document.getElementsByTagName('head')[0];
  var style = document.createElement('link');
  style.type = 'text/css';
  style.rel = 'stylesheet';
  style.href = url;
  head.appendChild(style);
}

SPOCustomUI.init = function (whenReadyDoFunc) {
  // avoid executing inside iframes (used by SharePoint for dialogs)
  if (self !== top) return;

  if (!window.jQuery) {
    // jQuery is needed for Custom Bar to run
    setTimeout(function () { SPOCustomUI.init(whenReadyDoFunc); }, 50);
  } else {
    $(function () {
      SPOCustomUI.setUpCustomFooter();
      whenReadyDoFunc();
    });
  }
}

// The following initializes the custom footer with some fake links
SPOCustomUI.init(function () {
  var currentScriptUrl;

  var currentScript = document.querySelectorAll("script[src*='SPOCustomUI']");
  if (currentScript.length > 0) {
    currentScriptUrl = currentScript[0].src;
  }
  if (currentScriptUrl != undefined) {
    var currentScriptBaseUrl = currentScriptUrl.substring(0, currentScriptUrl.lastIndexOf('/') + 1);
    SPOCustomUI.loadCSS(currentScriptBaseUrl + 'SPOCustomUI.css');
  }

  SPOCustomUI.addCustomFooterText('SPOFooterCopyright', '&copy; 2017, Contoso Inc.');
  SPOCustomUI.addCustomFooterLink('SPOFooterCRMLink', 'CRM', 'CRM.aspx');
  SPOCustomUI.addCustomFooterLink('SPOFooterSearchLink', 'Search Center', 'SearchCenter.aspx');
  SPOCustomUI.addCustomFooterLink('SPOFooterPrivacyLink', 'Privacy Policy', 'Privacy.aspx');
});

In der folgenden Abbildung ist die Ausgabe der vorherigen benutzerdefinierten Aktion auf der Startseite einer klassischen Website enthalten.

Die benutzerdefinierte Fußzeile auf einer klassischen Seite

Zum Migrieren der vorherigen Lösung zur modernen Benutzeroberfläche führen Sie die folgenden Schritte aus.

Erstellen einer neuen SharePoint-Framework-Lösung

  1. Erstellen Sie in der Konsole einen neuen Ordnern für Ihr Projekt:

    md spfx-react-custom-footer
    
  2. Wechseln Sie zum Projektordner:

    cd spfx-react-custom-footer
    
  3. Führen Sie im Projektordner den SharePoint Framework-Yeoman-Generator aus, um ein Gerüst für ein neues SharePoint Framework-Projekt zu erstellen:

    yo @microsoft/sharepoint
    
  4. Wenn Sie dazu aufgefordert werden, geben Sie die folgenden Werte ein (wählen Sie für alle unten nicht aufgeführten Eingabeaufforderungen die Standardoption aus):

    • Wie lautet der Name Ihrer Lösung?: spfx-react-custom-footer
    • Welche Basislinienpakete möchten Sie für Ihre Komponente(n) als Ziel festlegen? Nur SharePoint Online (neustes)
    • Welchen Typ von clientseitiger Komponente möchten Sie erstellen?: Erweiterung
    • Welchen Typ von clientseitiger Erweiterung möchten Sie erstellen? Application Customizer
    • Wie heißt Ihr Field Customizer? CustomFooter

    An diesem Punkt installiert Yeoman die erforderlichen Abhängigkeiten und erstellt ein Gerüst für die Lösungsdateien und Ordner sowie die CustomFooter-Erweiterung. Das kann einige Minuten dauern.

  5. Starten Sie Visual Studio Code (oder den Code-Editor Ihrer Wahl), und beginnen Sie, die Lösung zu entwickeln. Zum Starten von Visual Studio Code können Sie die folgende Anweisung ausführen.

    code .
    

Definieren der neuen Benutzeroberflächenelemente

Die Benutzeroberflächenelemente der benutzerdefinierte Fußzeile werden mit React und einer benutzerdefinierten React-Komponente gerendert. Sie können die Ui-Elemente der Beispielfußzeile mit der gewünschten Technologie erstellen. In diesem Lernprogramm verwenden wir React, um die Office UI Fabric-Komponenten für React zu verwenden.

  1. Öffnen Sie den Ordner ./src/extensions/customFooter/CustomFooterApplicationCustomizer.manifest.json . Kopieren Sie den Wert der Eigenschaft id, und bewahren Sie ihn an einem sicheren Ort auf, da Sie ihn später benötigen.

  2. Öffnen Sie die Datei ./src/extensions/customFooter/CustomFooterApplicationCustomizer.ts, und importieren Sie die Typen PlaceholderContent und PlaceholderName aus dem Paket @microsoft/sp-application-base.

    Fügen Sie am Anfang der Datei die import -Direktiven für React hinzu.

    Im folgenden Codeauszug ist der Abschnitt für die Importe der Datei CustomFooterApplicationCustomizer.ts enthalten.

    import * as React from 'react';
    import * as ReactDom from 'react-dom';
    
    import { override } from '@microsoft/decorators';
    import { Log } from '@microsoft/sp-core-library';
    import {
      BaseApplicationCustomizer,
      PlaceholderContent,
      PlaceholderName
    } from '@microsoft/sp-application-base';
    import { Dialog } from '@microsoft/sp-dialog';
    
    import * as strings from 'CustomFooterApplicationCustomizerStrings';
    import CustomFooter from './components/CustomFooter';
    
  3. Suchen Sie nach der Definition der CustomFooterApplicationCustomizer-Klasse, und deklarieren Sie einen neuen privaten Member namens bottomPlaceholder des Typs PlaceholderContent | undefined.

  4. Rufen Sie nun innerhalb der Außerkraftsetzung der onInit()-Methode eine benutzerdefinierte Funktion namens renderPlaceHolders auf, und definieren Sie diese Funktion.

    Im folgenden Codeauszug sehen Sie die Implementierung der benutzerdefinierten Application Customizer-Klasse in der Fußzeile.

    /** A Custom Action which can be run during execution of a Client Side Application */
    export default class CustomFooterApplicationCustomizer
    extends BaseApplicationCustomizer<ICustomFooterApplicationCustomizerProperties> {
    
      // This private member holds a reference to the page's footer
      private _bottomPlaceholder: PlaceholderContent | undefined;
    
      @override
      public onInit(): Promise<void> {
        Log.info(LOG_SOURCE, `Initialized ${strings.Title}`);
    
        let message: string = this.properties.testMessage;
        if (!message) {
          message = '(No properties were provided.)';
        }
    
        // Call render method for rendering the needed html elements
        this._renderPlaceHolders();
    
        return Promise.resolve();
      }
    
      private _renderPlaceHolders(): void {
    
        // Handling the bottom placeholder
        if (!this._bottomPlaceholder) {
          this._bottomPlaceholder =
            this.context.placeholderProvider.tryCreateContent(PlaceholderName.Bottom);
    
          // The extension should not assume that the expected placeholder is available.
          if (!this._bottomPlaceholder) {
            console.error('The expected placeholder (Bottom) was not found.');
            return;
          }
    
          const element: React.ReactElement<{}> = React.createElement(CustomFooter);
    
          ReactDom.render(element, this._bottomPlaceholder.domElement);
        }
      }
    }
    

    Die renderPlaceHolders()-Methode sucht zunächst nach dem Platzhalter des Typs Bottom und zeigt ggf. den Inhalt an. Tatsächlich erstellt der Code ganz am Ende der renderPlaceHolders() -Methode eine neue Instanz einer CustomFooter React Komponente und rendert sie innerhalb des Platzhalters am unteren Rand der Seiten (d. a. dort, wo die Fußzeile gerendert werden soll).

    Hinweis

    Die React-Komponente ersetzt in der modernen Benutzeroberfläche die JavaScript-Datei des klassischen Modells. Sie können die gesamte Fußzeile mithilfe von reinem JavaScript-Code rendern und den größten Teil des bereits vorhandenen Codes wiederverwenden. Es wird jedoch empfohlen, die Implementierung nicht nur im Hinblick auf Technologie, sondern auch im Hinblick auf den Code zu aktualisieren.

  5. Fügen Sie im Ordner src/extensions/customFooter einen neuen Ordner mit dem Namen components hinzu.

  6. Erstellen Sie in dem neuen Ordner eine neue Datei, und nennen Sie sie CustomFooter.tsx.

    Fügen Sie dieser Datei den folgenden Code hinzu:

    import * as React from 'react';
    import { CommandButton } from 'office-ui-fabric-react/lib/Button';
    
    export default class CustomFooter extends React.Component<{}, {}> {
      public render(): React.ReactElement<{}> {
        return (
          <div className={`ms-bgColor-neutralLighter ms-fontColor-white`}>
            <div className={`ms-bgColor-neutralLighter ms-fontColor-white`}>
              <div className={`ms-Grid`}>
                <div className="ms-Grid-row">
                  <div className="ms-Grid-col ms-sm2 ms-md2 ms-lg2">
                    <CommandButton
                        data-automation="CopyRight"
                        href={`CRM.aspx`}>&copy; 2017, Contoso Inc.</CommandButton>
                  </div>
                  <div className="ms-Grid-col ms-sm2 ms-md2 ms-lg2">
                    <CommandButton
                            data-automation="CRM"
                            iconProps={ { iconName: 'People' } }
                            href={`CRM.aspx`}>CRM</CommandButton>
                  </div>
                  <div className="ms-Grid-col ms-sm2 ms-md2 ms-lg2">
                    <CommandButton
                            data-automation="SearchCenter"
                            iconProps={ { iconName: 'Search' } }
                            href={`SearchCenter.aspx`}>Search Center</CommandButton>
                  </div>
                  <div className="ms-Grid-col ms-sm2 ms-md2 ms-lg2">
                    <CommandButton
                        data-automation="Privacy"
                        iconProps={ { iconName: 'Lock' } }
                        href={`Privacy.aspx`}>Privacy Policy</CommandButton>
                  </div>
                  <div className="ms-Grid-col ms-sm4 ms-md4 ms-lg4"></div>
                </div>
              </div>
            </div>
          </div>
        );
      }
    }
    

    Informationen zum Schreiben einer React-Komponente sind in diesem Dokument nicht enthalten. Beachten Sie die import Anweisungen am Anfang, in denen die Komponente React importiert, und die CommandButton React Komponente aus der Office UI Fabric-Komponentenbibliothek.

    In der render()-Methode der Komponente wird die Ausgabe von CustomFooter mit einigen Instanzen der CommandButton-Komponente für die Links in der Fußzeile definiert. Die HTML-Ausgabe ist in ein Rasterlayout von Office UI Fabric eingeschlossen.

    Hinweis

    Weitere Informationen zum Rasterlayout von Office UI Fabric finden Sie unter Dynamisches Layout.

    In der folgenden Abbildung ist die resultierende Ausgabe enthalten.

    Die auf einer modernen Website gerenderte benutzerdefinierte Fußzeile

Testen der Lösung im Debugmodus

  1. Kehren Sie zum Konsolenfenster zurück, und führen Sie den folgenden Befehl aus, um die Lösung zu erstellen und den lokalen Node.js-Server zum Hosten der Lösung auszuführen.

    gulp serve --nobrowser
    
  2. Öffnen Sie jetzt Ihren bevorzugten Browser, und wechseln Sie zu einer „modernen“ Seite einer beliebigen „modernen“ Teamwebsite. Hängen Sie jetzt die folgenden Abfragezeichenfolgeparameter an die Seiten-URL an.

    ?loadSPFX=true&debugManifestsFile=https://localhost:4321/temp/manifests.js&customActions={"82242bbb-f951-4c71-a978-80eb8f35e4c1":{"location":"ClientSideExtension.ApplicationCustomizer"}}
    

    Ersetzen Sie in dieser Abfragezeichenfolge die GUID durch den id-Wert aus der Datei CustomFooterApplicationCustomizer.manifest.json.

    Beachten Sie, dass Beim Ausführen der Seitenanforderung ein Warnmeldungsfeld mit dem Titel "Debugskripts zulassen?" angezeigt wird, in dem Sie aus Sicherheitsgründen Ihre Zustimmung zum Ausführen von Code von localhost anfordern. Wenn Sie die Projektmappe lokal debuggen und testen möchten, müssen Sie ihr das Laden von Debugskripts erlauben.

    Hinweis

    Alternativ können Sie Serverkonfigurationseinträge in der config/serve.json-Datei in Ihrem Projekt erstellen, um das Erstellen der Abfragezeichenfolgenparameter zum Debuggen zu automatisieren, wie in diesem Dokument beschrieben: Debuggen von SharePoint Framework-Lösungen auf modernen SharePoint-Seiten

Packen und Hosten der Lösung

Wenn Sie mit dem Ergebnis zufrieden sind, können Sie die Lösung nun packen und in der eigentlichen Hostinginfrastruktur hosten.

Bevor Sie das Bundle und das Paket erstellen, müssen Sie eine XML-Feature-Framework-Datei deklarieren, um die Erweiterung bereitzustellen.

Überprüfen von Feature-Framework-Elementen

  1. Öffnen Sie im Code-Editor die Datei ./sharepoint/assets/elements.xml. Der folgende Codeauszug gibt an, wie die Datei aussehen sollte.

    <?xml version="1.0" encoding="utf-8"?>
    <Elements xmlns="http://schemas.microsoft.com/sharepoint/">
      <CustomAction
          Title="CustomFooter"
          Location="ClientSideExtension.ApplicationCustomizer"
          ClientSideComponentId="82242bbb-f951-4c71-a978-80eb8f35e4c1">
      </CustomAction>
    </Elements>
    

    Wie Sie sehen können, ähnelt sie der SharePoint-Feature-Framework-Datei des klassischen Modells, sie verwendet jedoch das ClientSideComponentId-Attribut für den Verweis auf die id der benutzerdefinierten Erweiterung. Sie können auch ein ClientSideComponentProperties Attribut hinzufügen, wenn Sie benutzerdefinierte Einstellungen für die Erweiterung bereitstellen müssen, was in diesem Tutorial nicht der Fall ist.

  2. Öffnen Sie den Ordner ./config/package-solution.json der Projektmappe. In der Datei sehen Sie, dass im Abschnitt ein Verweis auf die elements.xml Datei vorhanden assets ist.

    {
      "$schema": "https://developer.microsoft.com/json-schemas/spfx-build/package-solution.schema.json",
      "solution": {
        "name": "spfx-react-custom-footer-client-side-solution",
        "id": "911728a5-7bde-4453-97b2-2eba59277ed3",
        "version": "1.0.0.0",
        "features": [
        {
          "title": "Application Extension - Deployment of custom action.",
          "description": "Deploys a custom action with ClientSideComponentId association",
          "id": "f16a2612-3163-46ad-9664-3d3daac68cff",
          "version": "1.0.0.0",
          "assets": {
            "elementManifests": [
              "elements.xml"
            ]
          }
        }]
      },
      "paths": {
        "zippedPackage": "solution/spfx-react-custom-footer.sppkg"
      }
    }
    

Bündeln, Packen und Bereitstellen der Lösung

Als Nächstes müssen Sie das Lösungsbundle im App-Katalog bündeln und packen. Um diese Aufgabe auszuführen, gehen Sie folgendermaßen vor.

Vorbereiten und Bereitstellen der Lösung für den SharePoint Online-Mandanten:

  1. Führen Sie die folgende Aufgabe aus, um Ihre Lösung in einem Bundle zu packen. Dadurch wird ein Releasebuild Ihres Projekts erstellt:

    gulp bundle --ship
    
  2. Führen Sie die folgende Aufgaben aus, um Ihre Lösung zu packen. Dieser Befehl erstellt ein *.sppkg-Paket im Ordner sharepoint/solution .

    gulp package-solution --ship
    
  3. Laden Sie das neu erstellte Paket mit ihrer clientseitigen Lösung in den App-Katalog in Ihrem Mandanten hoch. Alternativ können Sie es auch per Drag-and-Drop verschieben. Klicken Sie dann auf die Schaltfläche Bereitstellen.

Installieren und Ausführen der Lösung

  1. Öffnen Sie den Browser, und navigieren Sie zu der gewünschten modernen Zielwebsite.

  2. Navigieren Sie zur Seite Websiteinhalte, und wählen Sie App, um eine neue App hinzuzufügen.

  3. Wählen Sie zum Installieren einer neuen App Von Ihrer Organisation aus, um die im App-Katalog verfügbaren Lösungen zu durchsuchen.

  4. Wählen Sie die Lösung mit dem Namen spfx-react-custom-footer-client-side-solution aus, und installieren Sie sie auf der Zielwebsite.

    Hinzufügen einer App-Benutzeroberfläche zum Hinzufügen der Lösung zu einer Website

  5. Aktualisieren Sie nach Abschluss der Installation der Anwendung die Seite, oder wechseln Sie zur Startseite der Website. Die benutzerdefinierte Fußzeile sollte in Aktion angezeigt werden.

Genießen Sie Ihre neue benutzerdefinierte Fußzeile, die mit den SharePoint-Framework-Erweiterungen erstellt wurde!

Siehe auch