Erstellen Ihrer ersten Formularanpassungserweiterung
Formularanpassungen sind SharePoint-Framework Komponenten, mit denen Sie die Formularoberfläche in einer Listen- oder Bibliotheksebene überschreiben können, indem Sie die Komponente dem verwendeten Inhaltstyp zuordnen. Komponenten der Formularanpassung können in SharePoint Online verwendet werden, und Sie erstellen sie mit modernen JavaScript-Tools und -Bibliotheken.
Wichtig
Der Formularanpassungsdienst wurde als Teil der SharePoint-Framework 1.15 veröffentlicht. Stellen Sie daher sicher, dass Sie die richtige Version in Ihrer Umgebung verwenden. Ausführliche Informationen finden Sie in den Versionshinweisen zu Version 1.15 .
Tipp
Die Ausgabe dieses Tutorials finden Sie auf GitHub.
Erstellen eines Erweiterungsprojekts
Erstellen Sie an einem Speicherort Ihrer Wahl ein neues Projektverzeichnis:
md form-customizer
Wechseln Sie in das Projektverzeichnis:
cd form-customizer
Führen Sie den Yeoman-SharePoint-Generator aus, um eine neue HelloWorld-Erweiterung zu erstellen:
yo @microsoft/sharepoint
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 ihr Lösungsname?: Form-Customizer
- Welchen Typ von clientseitiger Komponente möchten Sie erstellen?: Erweiterung
- Welchen Typ von clientseitiger Erweiterung möchten Sie erstellen? Formularanpassung
- Wie lautet ihr Name des Formularanpassungsgebers? HelloWorld
- Welche Vorlage möchten Sie verwenden?: Kein JavaScript-Framework
An diesem Punkt installiert Yeoman die erforderlichen Abhängigkeiten und erstellt ein Gerüst für die Lösungsdateien sowie die HelloWorld-Erweiterung. Das kann einige Minuten dauern.
Geben Sie Folgendes in die Konsole ein, um Visual Studio Code zu starten.
code .
Hinweis
Da die clientseitige SharePoint-Lösung auf HTML/TypeScript basiert, können Sie zur Erstellung Ihrer Erweiterung jeden Code-Editor verwenden, der clientseitige Entwicklung unterstützt.
Öffnen Sie die Datei ./src/extensions/helloWorld/HelloWorldFormCustomizer.manifest.json .
Diese Datei definiert Ihren Erweiterungstyp und einen eindeutigen Bezeichner
id
für Ihre Erweiterung, der verwendet werden kann, um festzulegen, dass in der Inhaltstypebene verwendet werden soll, um ein benutzerdefiniertes Rendering mit dieser Komponente zu ermöglichen.
Programmieren des Formularanpassungsmodus
Öffnen Sie die Datei ./src/extensions/helloWorld/HelloWorldFormCustomizer.ts .
Beachten Sie, dass die Basisklasse für den Formularanpasser aus dem Paket sp-listview-extensibility importiert wird, das SharePoint-Framework code enthält, der für den Formularanpasser erforderlich ist.
import { Log } from '@microsoft/sp-core-library';
import {
BaseFormCustomizer
} from '@microsoft/sp-listview-extensibility';
Die Logik für Den Formularanpassunger ist in den onInit()
Methoden , render()
und onDispose()
enthalten.
onInit()
ist der Ort, an dem Sie das setup ausführen, das für Ihre Erweiterung erforderlich ist. Dieses Ereignis tritt auf, nachdemthis.context
undthis.properties
zugewiesen wurden, jedoch bevor das Seiten-DOM bereit ist. Wie bei Webparts gibt eine Zusage zurück, die Sie für asynchrone Vorgänge verwenden können.render()
Wird erst aufgerufen,onInit()
wenn Ihre Zusage aufgelöst wurde. Wenn Sie dies nicht benötigen, geben Sie einfachPromise.resolve<void>();
zurück.render()
tritt auf, wenn die Komponente gerendert wird. Die Methode bietet einevent.domElement
-HTML-Element, in das der Code den Inhalt schreiben kann.onDispose()
tritt unmittelbar vor dem Löschen des Formularhostelements auf. Es kann verwendet werden, um alle Ressourcen freizugeben, die während des Formularrenderings zugeordnet wurden. Wennrender()
ein React-Element bereitgestellt hat, mussonDispose()
zum Freigeben verwendet werden; anderenfalls würde ein Ressourcenverlust auftreten.
Im Folgenden sind die Inhalte von render()
und onDispose()
in der Standardlösung aufgeführt:
public render(): void {
// Use this method to perform your custom rendering.
this.domElement.innerHTML = `<div class="${ styles.helloWorld }"></div>`;
}
public onDispose(): void {
// This method should be used to free any resources that were allocated during rendering.
super.onDispose();
}
Da die Benutzerdefinierte Formularkomponente standardmäßig keine Informationen rendert, aktualisieren wir die Rendermethode wie folgt.
public render(): void {
// Use this method to perform your custom rendering.
this.domElement.innerHTML = `<div class="${ styles.helloWorld }"><h1>Super cool custom form component</h1></div>`;
}
Debuggen des Formularanpassers
Sie können Ihren Formularanpasser auf einer SharePoint Online-Livewebsite testen und debuggen. Dazu müssen Sie Ihre Anpassungen nicht im Mandanten-App-Katalog bereitstellen, was das Debuggen einfach und effizient macht.
Um Ihre Erweiterung zu testen, müssen Sie zuerst eine Liste erstellen, um den Customizer zu testen. Wechseln Sie daher zu der Website in Ihrem SharePoint Online-Mandanten, auf der Sie den Formularanpasser testen möchten.
Wählen Sie auf der Symbolleiste Neu, und wählen Sie dann Liste.
Wählen Sie leere Liste aus der neuen Benutzeroberfläche für die Listenerstellung aus.
Erstellen Sie eine neue Liste mit dem Namen Business, und wählen Sie dann Erstellen aus.
Öffnen Sie in Visual Studio Code die Datei ./config/serve.json .
Aktualisieren Sie die
pageUrl
Attribute so, dass sie mit einer URL der Liste übereinstimmen, die wir in den Vorschauschritten erstellt haben. Nach den Änderungen sollte Ihre "serve.json"- Datei wie der folgende Code aussehen:{ "$schema": "https://developer.microsoft.com/json-schemas/spfx-build/spfx-serve.schema.json", "port": 4321, "https": true, "serveConfigurations": { "default": { "pageUrl": "https://yourtenant.sharepoint.com/sites/demo/_layouts/15/SPListForm.aspx", "formCustomizer": { "componentId": "fb3e7dee-a6fa-4e80-add1-e06081167bb5", "PageType": 8, "RootFolder": "/sites/demo/Lists/business", "properties": { "sampleText": "Value" } }
Lassen Sie uns einige bestimmte Themen aus der Datei "serve.json" aufrufen.
- Sie können mehrere verschiedene Konfigurationen sehen, die verwendet werden können, um neue Formulare mit bestimmten Abfrageparameterunterschieden zu debuggen, zu bearbeiten und anzuzeigen. Sie können die verwendete Konfiguration in Ihrem gulp serve-Befehl definieren, z. B. als
gulp serve --config=helloWorld_EditForm
- componentId wird automatisch der ersten Listenformatierungskomponente in Ihrer Lösung zugeordnet (wenn Sie über mehrere Komponenten verfügen).
- Zur Vereinfachung des Debuggens müssen Sie keine Zielinhaltstyp-ID definieren, der die Komponente zugeordnet ist. In der Laufzeit wird die Zuordnung jedoch auf Inhaltstypebene ausgeführt, indem mindestens eine der folgenden Eigenschaften im Inhaltstyp aktualisiert wird:
- Contenttype. NewFormClientSideComponentId – Komponenten-ID für neues Formular
- Contenttype. NewFormClientSideComponentProperties – optionale Konfigurationsdetails
- Contenttype. DispFormClientSideComponentId – Komponenten-ID zum Bearbeiten des Formulars
- Contenttype. DispFormClientSideComponentProperties – optionale Konfigurationsdetails
- Contenttype. EditFormClientSideComponentId – Anzeigeformular für komponenten-ID
- Contenttype. EditFormClientSideComponentProperties – optionale Konfigurationsdetails
- Sie können mehrere verschiedene Konfigurationen sehen, die verwendet werden können, um neue Formulare mit bestimmten Abfrageparameterunterschieden zu debuggen, zu bearbeiten und anzuzeigen. Sie können die verwendete Konfiguration in Ihrem gulp serve-Befehl definieren, z. B. als
Zunächst führen Sie den folgenden Befehl aus, um den Code zu kompilieren und die Dateien auf Ihrem lokalen Computer zu hosten:
gulp serve
Wenn der Code ohne Fehler kompiliert wurde, verarbeitet er das resultierende Manifest von https://localhost:4321.
Dadurch wird Ihr Standardbrowser gestartet und die in der Datei serve.json definierte Seite geladen.
Klicken Sie bei Aufforderung auf Debugskripts laden, um das Laden der Debugmanifeste zu akzeptieren.
Beachten Sie, wie die benutzerdefinierte Komponente auf der Seite basierend auf dem benutzerdefinierten Inhalt gerendert wird, den wir auf die Rendermethode aktualisiert haben.
Hinzufügen von Bearbeitungsfunktionen für Formularelemente zum Beispiel
Nachdem wir nun die Baselinekomponente erstellt und getestet haben, ob sie ordnungsgemäß funktioniert. Wir erstellen eine separate Renderinglogik zum Anzeigen, Bearbeiten und neuen Formularen und zur Unterstützung des Speicherns neuer Elemente in der Liste.
Öffnen Sie die Datei ./src/extensions/helloWorld/loc/myStrings.d.ts, und fügen Sie der IHelloWorldFormCustomizerStrings-Schnittstelle einen neuen Titel hinzu. Die Schnittstelle sollte nach ihren Bearbeitungen wie folgt aussehen.
declare interface IHelloWorldFormCustomizerStrings { Save: string; Cancel: string; Close: string; Title: string; }
Öffnen Sie die Datei ./src/extensions/helloWorld/loc/en-us.js , und fügen Sie der Datei eine neue Title-Zeichenfolge hinzu. Der Dateiinhalt sollte nach ihren Bearbeitungen wie folgt aussehen.
define([], function() { return { "Save": "Save", "Cancel": "Cancel", "Close": "Close", "Title": "Title" } });
Öffnen Sie die Datei ./src/extensions/helloWorld/HelloWorldFormCustomizer.module.scss , und aktualisieren Sie die Formatdefinition wie folgt. Wir fügen die Fehlerformatierung für die Komponente hinzu.
.helloWorld { background-color: "[theme:white, default:#ffffff]"; color: "[theme:themePrimary, default:#0078d4]"; padding: 0.5rem; .error { color: red; } }
Wechseln Sie zum Anfang der Datei HelloWorldFormCustomizer.ts .
Suchen Sie die Zeile
import styles from './HelloWorldFormCustomizer.module.scss';
, und fügen Sie die folgenden Zeilen unmittelbar danach hinzu:import { FormDisplayMode } from '@microsoft/sp-core-library'; import { SPHttpClient, SPHttpClientResponse } from '@microsoft/sp-http';
Fügen Sie _item und _etag privaten Typen in die HelloWorldFormCustomizer-Klasse ein, wie in diesem Codeausschnitt gezeigt. Beachten Sie, dass die Klassendefinition bereits im Code vorhanden ist.
// This already exists in YOUR code export default class HelloWorldFormCustomizer extends BaseFormCustomizer<IHelloWorldFormCustomizerProperties> { // Added for the item to show in the form; use with edit and view form private _item: { Title?: string; }; // Added for item's etag to ensure integrity of the update; used with edit form private _etag?: string;
Aktualisieren Sie die onInit()- Methode wie folgt. Dieser Code verwendet this.displayMode , um den Status des Renderings zu bestimmen, und ruft dann das ausgewählte Listenelement ab, wenn dies erforderlich ist.
public onInit(): Promise<void> { if (this.displayMode === FormDisplayMode.New) { // we're creating a new item so nothing to load return Promise.resolve(); } // load item to display on the form return this.context.spHttpClient .get(this.context.pageContext.web.absoluteUrl + `/_api/web/lists/getbytitle('${this.context.list.title}')/items(${this.context.itemId})`, SPHttpClient.configurations.v1, { headers: { accept: 'application/json;odata.metadata=none' } }) .then(res => { if (res.ok) { // store etag in case we'll need to update the item this._etag = res.headers.get('ETag'); return res.json(); } else { return Promise.reject(res.statusText); } }) .then(item => { this._item = item; return Promise.resolve(); }); }
Aktualisieren Sie die render()-Methode wie folgt. Rendern Sie das Formular abhängig vom Anzeigemodus des Formulars entweder nur in der Anzeige oder im Bearbeitungsmodus. In diesem Fall verwenden wir die gleiche Renderig für neue und Bearbeitungsfunktionen, aber Sie können bei Bedarf problemlos eine dedizierte Option haben.
public render(): void { // render view form if (this.displayMode === FormDisplayMode.Display) { this.domElement.innerHTML = `<div class="${styles.basics}"> <label for="title">${strings.Title}</label> <br /> ${this._item?.Title} <br /> <br /> <input type="button" id="cancel" value="${strings.Close}" /> </div>`; document.getElementById('cancel').addEventListener('click', this._onClose.bind(this)); } // render new/edit form else { this.domElement.innerHTML = `<div class="${styles.basics}"> <label for="title">${strings.Title}</label><br /> <input type="text" id="title" value="${this._item?.Title || ''}"/> <br /> <br /> <input type="button" id="save" value="${strings.Save}" /> <input type="button" id="cancel" value="${strings.Cancel}" /> <br /> <br /> <div class="${styles.error}"></div> </div>`; document.getElementById('save').addEventListener('click', this._onSave.bind(this)); document.getElementById('cancel').addEventListener('click', this._onClose.bind(this)); } }
Aktualisieren Sie die _onSave Methoden in der HelloWorldFormCustomizer-Klasse wie folgt.
private _onSave = async (): Promise<void> => { // disable all input elements while we're saving the item this.domElement.querySelectorAll('input').forEach(el => el.setAttribute('disabled', 'disabled')); // reset previous error message if any this.domElement.querySelector(`.${styles.error}`).innerHTML = ''; let request: Promise<SPHttpClientResponse>; const title: string = (document.getElementById('title') as HTMLInputElement).value; switch (this.displayMode) { case FormDisplayMode.New: request = this._createItem(title); break; case FormDisplayMode.Edit: request = this._updateItem(title); } const res: SPHttpClientResponse = await request; if (res.ok) { // You MUST call this.formSaved() after you save the form. this.formSaved(); } else { const error: { error: { message: string } } = await res.json(); this.domElement.querySelector(`.${styles.error}`).innerHTML = `An error has occurred while saving the item. Please try again. Error: ${error.error.message}`; this.domElement.querySelectorAll('input').forEach(el => el.removeAttribute('disabled')); } }
Fügen Sie der HelloWorldFormCustomizer-Klasseeine neue Methode _createItem hinzu.
private _createItem(title: string): Promise<SPHttpClientResponse> { return this.context.spHttpClient .post(this.context.pageContext.web.absoluteUrl + `/_api/web/lists/getByTitle('${this.context.list.title}')/items`, SPHttpClient.configurations.v1, { headers: { 'content-type': 'application/json;odata.metadata=none' }, body: JSON.stringify({ Title: title }) }); }
Fügen Sie der HelloWorldFormCustomizer-Klasseeine neue Methode _updateItem hinzu.
private _updateItem(title: string): Promise<SPHttpClientResponse> { return this.context.spHttpClient .post(this.context.pageContext.web.absoluteUrl + `/_api/web/lists/getByTitle('${this.context.list.title}')/items(${this.context.itemId})`, SPHttpClient.configurations.v1, { headers: { 'content-type': 'application/json;odata.metadata=none', 'if-match': this._etag, 'x-http-method': 'MERGE' }, body: JSON.stringify({ Title: title }) }); }
Jetzt ist der Code vollständig, um minimale Neu-, Bearbeitungs- und Anzeigefunktionen zu unterstützen, und Sie können die verschiedenen Funktionen mit verschiedenen Konfigurationen für das Debuggen testen.
Bereitstellung Ihrer Erweiterung
Wenn Sie bereit sind, Ihre Komponente zu verwenden, müssen Sie einige Schritte im Zusammenhang mit der Komponentenzuordnung zum Inhaltstyp berücksichtigen. Die Schritte für die Bereitstellung sind wie folgt:
- Bereitstellen einer Lösung im SharePoint-App-Katalog
- Installieren Sie die Lösung für die Websitesammlung, in der Sie die Erweiterung verwenden möchten, wenn Sie nicht die mandantenbereichsbezogene Bereitstellung verwenden.
- Ordnen Sie die benutzerdefinierte Komponente mithilfe der spezifischen Eigenschaften im ContentType-Objekt dem Inhaltstyp zu. Hierfür gibt es einige Optionen:
- Sie können die verwendete Liste und den Inhaltstyp aus Ihrer Lösung bereitstellen, wenn Sie die Website-bereichsbezogene Bereitstellungsoption verwenden.
- Sie können die Komponente inhaltstypen mithilfe von REST- oder CSOM-APIs zuordnen. Beachten Sie folgendes: Wenn Sie die Komponente in der Websitesammlung oder in der Hubebene des Inhaltstyps zuordnen, wird sie automatisch an alle neuen Inhaltstypinstanzen geerbt.