Créer votre première extension personnalisateur de formulaire
Les personnalisateurs de formulaire sont SharePoint Framework composants qui vous donnent la possibilité de remplacer l’expérience de formulaire au niveau d’une liste ou d’une bibliothèque en associant le composant au type de contenu utilisé. Les composants du personnalisateur de formulaire peuvent être utilisés dans SharePoint Online et vous les générez à l’aide d’outils et de bibliothèques JavaScript modernes.
Importante
Le personnalisateur de formulaire a été publié dans le cadre de la SharePoint Framework 1.15. Vérifiez donc que vous utilisez la version appropriée dans votre environnement. Pour plus d’informations, consultez les notes de publication v1.15 .
Conseil
Vous trouverez la sortie de ce didacticiel à partir de GitHub.
Créer un projet d’extension
Créez un nouveau répertoire de projet à l’emplacement de votre choix.
md form-customizer
Accédez au répertoire du projet.
cd form-customizer
Créez une extension HelloWorld en exécutant le générateur SharePoint Yeoman.
yo @microsoft/sharepoint
Lorsque vous y êtes invité, entrez les valeurs suivantes (sélectionnez l’option par défaut pour toutes les invites qui ne sont pas mentionnées ci-dessous) :
- Quel est le nom de votre solution ? : form-customizer
- Quel type de composant côté client voulez-vous créer ? : Extension
- Quel type d’extension côté client créer ? Personnalisateur de formulaire
- Quel est le nom de votre personnalisateur de formulaire ? HelloWorld
- Quel modèle souhaitez-vous utiliser ? : Aucune infrastructure JavaScript
À ce stade, Yeoman installe les dépendances requises et établit la structure des fichiers de la solution avec l’extension HelloWorld. Cette opération peut prendre quelques minutes.
Entrez les informations suivantes dans la console pour démarrer Visual Studio Code.
code .
Remarque
Étant donné que la solution côté client SharePoint utilise du code HTML/TypeScript, vous pouvez utiliser n’importe quel éditeur de code qui prend en charge le développement côté client pour créer votre extension.
Ouvrez le fichier ./src/extensions/helloWorld/HelloWorldFormCustomizer.manifest.json .
Ce fichier définit votre type d’extension et un identificateur
id
unique pour votre extension, qui peut être utilisé pour être utilisé au niveau du type de contenu pour activer un rendu personnalisé avec ce composant.
Coder votre personnalisateur de formulaire
Ouvrez le fichier ./src/extensions/helloWorld/HelloWorldFormCustomizer.ts .
Notez que la classe de base du personnalisateur de formulaire est importée à partir du package sp-listview-extensibility, qui contient SharePoint Framework code requis par le personnalisateur de formulaire.
import { Log } from '@microsoft/sp-core-library';
import {
BaseFormCustomizer
} from '@microsoft/sp-listview-extensibility';
La logique de votre personnalisateur de formulaire est contenue dans les onInit()
méthodes , render()
et onDispose()
.
onInit()
est l’endroit où vous allez exécuter la configuration nécessaire pour votre extension. Cet événement se produit après quethis.context
etthis.properties
ont été attribués, mais avant que la page DOM ne soit prête. Comme avec les composants WebPart,onInit()
retourne une promesse que vous pouvez utiliser pour effectuer des opérations asynchrones ;render()
n’est pas appelée tant que votre promesse n’est pas résolue. Si vous n’en avez pas besoin, renvoyez simplementPromise.resolve<void>();
.render()
se produit lorsque le composant est rendu. Il fournit un élément HTMLevent.domElement
où votre code peut écrire son contenu.onDispose()
se produit immédiatement avant la suppression de l’élément d’hôte de formulaire. Il peut être utilisé pour libérer toutes les ressources qui ont été allouées pendant le rendu du formulaire. Par exemple, sirender()
a monté un élément React,onDispose()
doit être utilisé pour le libérer ; sinon, une perte de ressource se produit.
Voici le contenu de render()
et onDispose()
de la solution par défaut :
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();
}
Comme par défaut, le composant customzier de formulaire n’affiche aucune information, nous allons mettre à jour la méthode render comme suit.
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>`;
}
Déboguer votre personnalisateur de formulaire
Vous pouvez tester et déboguer votre personnalisateur de formulaire dans un site SharePoint Online actif. Vous n’avez pas besoin de déployer vos personnalisations dans le catalogue d’applications client pour ce faire, ce qui rend l’expérience de débogage simple et efficace.
Pour tester votre extension, vous devez d’abord créer une liste pour tester le personnalisateur dans. Par conséquent, accédez au site de votre locataire SharePoint Online où vous souhaitez tester le personnalisateur de formulaire.
Dans la barre d’outils, sélectionnez Nouveau, puis Liste.
Choisissez Liste vide dans la nouvelle expérience de création de liste
Créez une liste nommée Business, puis sélectionnez Créer.
Dans Visual Studio Code, ouvrez le fichier ./config/serve.json .
Mettez à jour les
pageUrl
attributs pour qu’ils correspondent à l’URL de la liste que nous avons créée dans les étapes d’aperçu. Après les modifications, votre fichier serve.json doit ressembler au code suivant :{ "$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" } }
Nous allons appeler quelques rubriques spécifiques à partir du fichier serve.json
- Vous pouvez voir plusieurs configurations différentes qui peuvent être utilisées pour déboguer de nouveaux formulaires, modifier et afficher des formulaires avec des différences de paramètres de requête spécifiques. Vous pouvez définir la configuration utilisée dans votre commande gulp serve, par exemple en tant que
gulp serve --config=helloWorld_EditForm
- componentId est automatiquement associé pour être le premier composant de mise en forme de liste dans votre solution (si vous avez plusieurs composants)
- Pour simplifier le débogage, vous n’avez pas besoin de définir l’ID de type de contenu cible auquel le composant est associé, mais dans le runtime, l’association est effectuée au niveau du type de contenu en mettant à jour au moins l’une des propriétés suivantes dans le type de contenu :
- Contenttype. NewFormClientSideComponentId : ID de composant pour le nouveau formulaire
- Contenttype. NewFormClientSideComponentProperties : détails de configuration facultatifs
- Contenttype. DispFormClientSideComponentId : ID de composant pour le formulaire de modification
- Contenttype. DispFormClientSideComponentProperties : détails de configuration facultatifs
- Contenttype. EditFormClientSideComponentId : formulaire d’affichage de l’ID de composant
- Contenttype. EditFormClientSideComponentProperties : détails de configuration facultatifs
- Vous pouvez voir plusieurs configurations différentes qui peuvent être utilisées pour déboguer de nouveaux formulaires, modifier et afficher des formulaires avec des différences de paramètres de requête spécifiques. Vous pouvez définir la configuration utilisée dans votre commande gulp serve, par exemple en tant que
Compilez votre code et hébergez les fichiers compilés à partir de l’ordinateur local en exécutant la commande suivante :
gulp serve
Une fois que la compilation du code est terminée sans erreur, ce dernier sert au manifeste obtenu à partir de https://localhost:4321.
Cela démarre votre navigateur par défaut et charge la page définie dans le fichier serve.json .
Acceptez le chargement des manifestes de débogage en sélectionnant Charger les scripts de débogage lorsque vous y êtes invité.
Notez comment le composant personnalisé est rendu dans la page en fonction du contenu personnalisé que nous avons mis à jour vers la méthode render.
Ajouter des fonctionnalités de modification d’élément de formulaire à l’exemple
Maintenant que nous avons créé le composant de base de référence et testé qu’il fonctionne correctement. Nous allons créer une logique de rendu distincte pour l’affichage, la modification et les nouveaux formulaires, et pour prendre en charge l’enregistrement de nouveaux éléments dans la liste.
Ouvrez le fichier ./src/extensions/helloWorld/loc/myStrings.d.ts et ajoutez un nouveau titre à l’interface IHelloWorldFormCustomizerStrings . L’interface doit être la suivante après vos modifications.
declare interface IHelloWorldFormCustomizerStrings { Save: string; Cancel: string; Close: string; Title: string; }
Ouvrez le fichier ./src/extensions/helloWorld/loc/en-us.js et ajoutez une nouvelle chaîne title au fichier. Le contenu du fichier doit être le suivant après vos modifications.
define([], function() { return { "Save": "Save", "Cancel": "Cancel", "Close": "Close", "Title": "Title" } });
Ouvrez le fichier ./src/extensions/helloWorld/HelloWorldFormCustomizer.module.scss et mettez à jour la définition de style comme suit. Nous ajoutons un style d’erreur pour le composant.
.helloWorld { background-color: "[theme:white, default:#ffffff]"; color: "[theme:themePrimary, default:#0078d4]"; padding: 0.5rem; .error { color: red; } }
Accédez au haut du fichier HelloWorldFormCustomizer.ts .
Recherchez la ligne
import styles from './HelloWorldFormCustomizer.module.scss';
et ajoutez les lignes suivantes immédiatement après :import { FormDisplayMode } from '@microsoft/sp-core-library'; import { SPHttpClient, SPHttpClientResponse } from '@microsoft/sp-http';
Incluez _item et _etag types privés à l’intérieur de la classe HelloWorldFormCustomizer , comme indiqué dans cet extrait de code. Notez que la définition de classe existe déjà dans votre code.
// 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;
Mettez à jour la méthode onInit() comme suit. Ce code utilise this.displayMode pour déterminer l’état du rendu, puis extrait l’élément de liste sélectionné si nécessaire.
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(); }); }
Mettez à jour la méthode render() comme suit. Affichez le formulaire en mode affichage uniquement ou en mode édition, selon le mode d’affichage du formulaire. Dans ce cas, nous utilisons le même renderig pour l’expérience nouvelle et de modification, mais vous pouvez facilement avoir une option dédiée si nécessaire.
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)); } }
Mettez à jour les méthodes _onSave dans la classe HelloWorldFormCustomizer comme suit.
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')); } }
Ajoutez une nouvelle méthode _createItem à la classe HelloWorldFormCustomizer .
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 }) }); }
Ajoutez une nouvelle méthode _updateItem à la classe HelloWorldFormCustomizer .
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 }) }); }
À présent, le code est complet pour prendre en charge les expériences Nouvelles, Modifier et Afficher minimales, et vous pouvez tester les différentes expériences à l’aide de différentes configurations pour le débogage.
Déploiement de votre extension
Chaque fois que vous êtes prêt à commencer à utiliser votre composant, il existe quelques étapes à prendre en compte concernant l’association du composant au type de contenu. Les étapes de déploiement sont les suivantes :
- Déployer la solution sur le catalogue d’applications SharePoint
- Installer la solution dans la collection de sites où vous souhaitez utiliser l’extension si vous n’utilisez pas le déploiement délimité au locataire
- Associez le composant personnalisé au type de contenu à l’aide des propriétés spécifiques dans l’objet ContentType. Il existe quelques options pour effectuer cette opération :
- Vous pouvez provisionner la liste et le type de contenu utilisés à partir de votre solution si vous utilisez l’option de déploiement délimitée au site
- Vous pouvez associer le composant à des types de contenu à l’aide d’API REST ou CSOM. Notez que si vous associez le composant dans la collection de sites ou au niveau du hub de type de contenu, il est automatiquement hérité de toutes les nouvelles instances de type de contenu