Partager via


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

  1. Créez un nouveau répertoire de projet à l’emplacement de votre choix.

    md form-customizer
    
  2. Accédez au répertoire du projet.

    cd form-customizer
    
  3. Créez une extension HelloWorld en exécutant le générateur SharePoint Yeoman.

    yo @microsoft/sharepoint
    
  4. 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.

  5. 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.

  6. 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 que this.context et this.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 simplement Promise.resolve<void>();.
  • render() se produit lorsque le composant est rendu. Il fournit un élément HTML event.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, si render() 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.

  1. 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.

  2. Dans la barre d’outils, sélectionnez Nouveau, puis Liste.

    Création d’une liste

  3. Choisissez Liste vide dans la nouvelle expérience de création de liste

    Sélection d’une liste vide

  4. Créez une liste nommée Business, puis sélectionnez Créer.

    Création d’une liste avec le nom des commandes

  5. 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
  6. 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.

    gulp serve

    Cela démarre votre navigateur par défaut et charge la page définie dans le fichier serve.json .

  7. Acceptez le chargement des manifestes de débogage en sélectionnant Charger les scripts de débogage lorsque vous y êtes invité.

    Accepter le chargement des scripts de débogage

    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.

    Affichage Liste avec du personnalisateur rendu avec outpu par défaut

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.

  1. 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;
    }
    
  2. 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"
      }
    });
    
  3. 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;
      }
    }
    
  4. Accédez au haut du fichier HelloWorldFormCustomizer.ts .

  5. 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';
    
  6. 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;
    
  7. 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();
        });
    }
    
  8. 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));
        }
      }
    
  9. 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'));
      }
    }
    
  10. 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
          })
        });
    }
    
  11. 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.

Formulaire personnalisé dans le contexte de SharePoint

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 :

  1. Déployer la solution sur le catalogue d’applications SharePoint
  2. 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
  3. 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 :
    1. 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
    2. 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