Présentation et configuration du modèle de transformation de page

Le cœur de la solution de transformation de page est le modèle qui alimente la transformation : le modèle indique au moteur quelles propriétés de composant WebPart sont importantes, vous permet de manipuler ces propriétés et de choisir dynamiquement un mappage pour votre composant WebPart. Le modèle de transformation de page est exprimé en XML et est fourni avec un schéma utilisé pour valider l’exactitude du modèle.

Importante

La modernisation de SharePoint PnP fait partie du Framework PnP et est en constante évolution, consultez les notes de publication pour rester à jour sur les dernières modifications. Si vous rencontrez des problèmes, veuillez le signaler dans la liste des problèmes de PnP Framework GitHub.

Architecture de haut niveau de transformation de page

L’image suivante représente les 4 étapes de la transformation de vos pages :

  1. Tout d’abord, fournissez au moteur de transformation un modèle de transformation de page. Ce modèle est un fichier XML qui décrit comment chaque composant WebPart classique doit être mappé avec un composant WebPart moderne équivalent. Pour chaque composant WebPart classique, le modèle contient une liste de propriétés pertinentes et d’informations de mappage. Pour en savoir plus, consultez l’article relatif à la présentation et configuration du modèle de transformation de page. Pour avoir une comparaison des composants WebPart classiques et des composants WebPart modernes, nous vous recommandons de consulter l’article relatif aux expériences de composant WebPart classique et moderne.
  2. L’étape suivante consiste à analyser la page à transformer : le moteur de transformation répartit la page dans une collection de composants WebPart (le texte wiki est réparti dans un ou plusieurs composants WebPart de texte wiki) et tente de détecter la mise en page utilisée.
  3. Les informations récupérées de l’analyse à l’étape 2 ne suffisent généralement pas à mapper le composant WebPart avec un composant WebPart moderne équivalent. C’est pourquoi, à l’étape 3, nous allons améliorer les informations en appelant des fonctions : ces fonctions prennent les propriétés récupérées à l’étape 2 et génèrent de nouvelles propriétés basées sur les propriétés entrées à l’étape 2. Après l’étape 3, nous avons toutes les informations nécessaires pour mapper le composant WebPart... sauf que nous devons éventuellement appeler le sélecteur défini pour comprendre le mappage dont nous aurons besoin si un composant WebPart classique peut être mappé à plusieurs configurations modernes.
  4. La dernière étape consiste à créer et configurer la page moderne, puis à y ajouter les composants WebPart modernes mappés.

transformation de page

Structure du modèle de transformation de page

Quand vous ouvrez le modèle de transformation de page, les éléments de niveau supérieur suivants apparaissent :

  • BaseWebPart : cet élément contient la configuration qui s’applique à tous les composants WebPart. Par exemple, il indique que la propriété « Titre » est extraite pour tous les composants WebPart. C’est également l’emplacement qui définit le mappage de composants WebPart par défaut : si un composant WebPart n’a aucun mappage défini, le moteur revient à ce mappage pour représenter le composant WebPart sur la page cible.

  • AddOns : en tant qu’utilisateur de la transformation de page, vous devrez peut-être appliquer une logique personnalisée pour répondre à vos besoins, par exemple, vous devez transformer une propriété donnée de manière à ce qu’elle fonctionne avec votre composant WebPart SPFX personnalisé. L’infrastructure prend en charge cet aspect en vous permettant d’ajouter vos assemblies avec les fonctions et les sélecteurs. En les définissant simplement dans la section AddOn et en référençant ensuite vos fonctions et vos sélecteurs personnalisés en y ajoutant en préfixe un nom donné, vous demandez à la transformation de page d’utiliser votre code personnalisé.

  • WebParts : cet élément contient des informations pour chaque composant WebPart à transformer. Pour chaque composant WebPart, vous trouverez une définition des propriétés à utiliser, les fonctions à exécuter sur ces propriétés, les mappages possibles qui définissent la cible de la transformation combinés à un sélecteur qui vous permet de sélectionner dynamiquement le mappage nécessaire.

De plus amples informations vous seront fournies dans les prochains chapitres.

Définition du composant WebPart dans le modèle de transformation de page

Nous allons analyser comment un composant WebPart est configuré dans le modèle de transformation de page. Pour cela, nous vous recommandons d’utiliser un exemple simplifié de la définition de XsltListViewWebPart :

      <!-- XsltListView web part -->
      <WebPart Type="Microsoft.SharePoint.WebPartPages.XsltListViewWebPart, Microsoft.SharePoint, Version=16.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c">
        <Properties>
          <Property Name="XmlDefinitionLink" Type="string" />
          <Property Name="ListUrl" Type="string" />
          <Property Name="ListId" Type="guid" Functions="{ListWebRelativeUrl} = ListAddWebRelativeUrl({ListId}); {ListServerRelativeUrl} = ListAddServerRelativeUrl({ListId})"/>
          <Property Name="Direction" Type="string"/>
          <Property Name="GhostedXslLink" Type="string" />
          <Property Name="DisableViewSelectorMenu" Type="bool"/>
          <Property Name="XmlDefinition" Type="string" Functions="{ListViewId} = ListDetectUsedView({ListId},{XmlDefinition})"/>
          <Property Name="SelectParameters" Type="string"/>
        </Properties>
        <!-- This selector outputs: Library, List  -->
        <Mappings Selector="ListSelectorListLibrary({ListId})">
          <Mapping Name="List" Default="true">
            <ClientSideText Text="You can map a source web part ({Title}) to a combination of modern web parts :-)" Order="10" />
            <ClientSideWebPart Type="List" Order="20" JsonControlData="&#123;&quot;serverProcessedContent&quot;&#58;&#123;&quot;htmlStrings&quot;&#58;&#123;&#125;,&quot;searchablePlainTexts&quot;&#58;&#123;&#125;,&quot;imageSources&quot;&#58;&#123;&#125;,&quot;links&quot;&#58;&#123;&#125;&#125;,&quot;dataVersion&quot;&#58;&quot;1.0&quot;,&quot;properties&quot;&#58;&#123;&quot;isDocumentLibrary&quot;&#58;false,&quot;selectedListId&quot;&#58;&quot;{ListId}&quot;,&quot;listTitle&quot;&#58;&quot;{Title}&quot;,&quot;selectedListUrl&quot;&#58;&quot;{ListServerRelativeUrl}&quot;,&quot;webRelativeListUrl&quot;&#58;&quot;{ListWebRelativeUrl}&quot;,&quot;webpartHeightKey&quot;&#58;4,&quot;selectedViewId&quot;&#58;&quot;{ListViewId}&quot;&#125;&#125;" />
          </Mapping>
          <Mapping Name="Library" Default="false">
            <ClientSideWebPart Type="List" Order="10" JsonControlData="&#123;&quot;serverProcessedContent&quot;&#58;&#123;&quot;htmlStrings&quot;&#58;&#123;&#125;,&quot;searchablePlainTexts&quot;&#58;&#123;&#125;,&quot;imageSources&quot;&#58;&#123;&#125;,&quot;links&quot;&#58;&#123;&#125;&#125;,&quot;dataVersion&quot;&#58;&quot;1.0&quot;,&quot;properties&quot;&#58;&#123;&quot;isDocumentLibrary&quot;&#58;true,&quot;selectedListId&quot;&#58;&quot;{ListId}&quot;,&quot;listTitle&quot;&#58;&quot;{Title}&quot;,&quot;selectedListUrl&quot;&#58;&quot;{ListServerRelativeUrl}&quot;,&quot;webRelativeListUrl&quot;&#58;&quot;{ListWebRelativeUrl}&quot;,&quot;webpartHeightKey&quot;&#58;4,&quot;selectedViewId&quot;&#58;&quot;{ListViewId}&quot;&#125;&#125;" />
          </Mapping>
        </Mappings>
      </WebPart>

Élément Properties

Pour chaque composant WebPart, le modèle définit les propriétés qui peuvent être utiles pour configurer le ou les composants WebPart modernes cibles. Si vous ratez certaines propriétés, vous pouvez simplement les étendre dans le modèle. Sur certaines propriétés, vous verrez un attribut Functions : cet attribut contient une ou plusieurs fonctions (séparez les fonctions via un ;) qui sont exécutés lorsque le composant WebPart source est mappé à un composant WebPart moderne cible. Voici l’anatomie d’une fonction :

{Output} = FunctionName({Input1}, {Input2})

Une fonction peut posséder une ou plusieurs valeurs d’entrée, notamment :

  • Les propriétés définies sur ce composant WebPart (par exemple, {ListId})
  • Les propriétés définies dans le composant WebPart de base (par exemple, {Title})
  • Les propriétés correspondant à la sortie des exécutions de la fonction précédente (par exemple, {ListWebRelativeUrl})
  • Les propriétés d’étendue de site par défaut : {Host}, {Web}, {Site}, {WebId}, {SiteId}

Lorsqu’une fonction s’exécute, sa sortie est soit :

  • Une valeur de chaîne unique : cette valeur ({Output} dans le modèle présenté) est ajoutée à la liste des propriétés du composant WebPart appelées « Output » et à la valeur renvoyée à partir de l’exécution de FunctionName.
  • Une liste de paires clé/valeur (chaîne de dictionnaire,chaîne<>) : dans ce cas, chaque paire clé/valeur retournée est ajoutée à la liste des propriétés du composant WebPart

Si la fonction ne définit pas le paramètre de sortie, la valeur de la propriété du composant WebPart qui définit la fonction est remplacée par le résultat de la fonction.

Voici un exemple pour éclaircir ce point :

<Property Name="ListId" Type="guid" Functions="FormatGuid({ListId})"/>

Supposons que la propriété du composant WebPart contienne à l’origine un GUID mis en forme de la manière suivante : {AAFAD7D0-D57A-4BB1-8706-969A608C686B}. Une fois que la fonction FormatGuid est exécutée, la valeur est définie sur la sortie de la fonction FormatGuid (par exemple, un GUID sans les crochets AAFAD7D0-D57A-4BB1-8706-969A608C686B).

Si une fonction renvoie plusieurs valeurs, chaque paire clé/valeur renvoyée qui existe déjà comme propriété du composant WebPart remplace la valeur de cette propriété.

Remarque

Toutes les fonctions prêtes à l’emploi sont décrites dans l’article sur les sélecteurs et fonctions de transformation de page

Élément Mappings

Cet élément définit une ou plusieurs configurations cibles possibles pour le composant WebPart source donné. Comme vous pouvez définir plusieurs cibles, un mécanisme doit être mis en place pour déterminer le mappage à utiliser :

  • Si l’élément Mapping contient un attribut « Selector » rempli, la sortie de l’exécution du sélecteur sert à rechercher le mappage approprié par son nom (par exemple, la fonction du sélecteur ListSelectorListLibrary renvoie « Library », ce qui génère le mappage « Library » en cours d’utilisation). Les sélecteurs sont identiques aux fonctions renvoyant une seule valeur. Ainsi, vous pouvez spécifier un attribut de composant WebPart comme entrée dans la fonction de votre sélecteur.
  • S’il n’y a qu’un seul mappage, celui-ci est pris en compte s’il n’y avait aucun résultat du sélecteur.
  • S’il n’y a aucun résultat du sélecteur et qu’il existe plusieurs mappages définis, le mappage marqué comme valeur par défaut est pris en compte.

Remarque

Tous les sélecteurs prêts à l’emploi sont décrits dans l’article Sélecteurs et fonctions de transformation de page

Vous trouverez ci-dessous une description de l’élément Mapping.

Élément Mapping

Dans un élément Mapping, vous pouvez avoir un ou plusieurs éléments ClientSideText ou ClientSideWebPart, comme indiqué dans l’extrait de code ci-dessous. Notez que vous pouvez exécuter des fonctions sur un mappage, ce qui est pratique si vous souhaitez effectuer un traitement uniquement si un mappage particulier a été sélectionné.

<Mapping Name="List" Default="true" Functions="{SampleVariable} = SampleFunction({ListId})>
  <ClientSideText Text="You can map a source web part ({Title}) to a combination of modern web parts :-)" Order="10" />
  <ClientSideWebPart Type="List" Order="20" JsonControlData="&#123;&quot;serverProcessedContent&quot;&#58;&#123;&quot;htmlStrings&quot;&#58;&#123;&#125;,&quot;searchablePlainTexts&quot;&#58;&#123;&#125;,&quot;imageSources&quot;&#58;&#123;&#125;,&quot;links&quot;&#58;&#123;&#125;&#125;,&quot;dataVersion&quot;&#58;&quot;1.0&quot;,&quot;properties&quot;&#58;&#123;&quot;isDocumentLibrary&quot;&#58;false,&quot;selectedListId&quot;&#58;&quot;{ListId}&quot;,&quot;listTitle&quot;&#58;&quot;{Title}&quot;,&quot;selectedListUrl&quot;&#58;&quot;{ListServerRelativeUrl}&quot;,&quot;webRelativeListUrl&quot;&#58;&quot;{ListWebRelativeUrl}&quot;,&quot;webpartHeightKey&quot;&#58;4,&quot;selectedViewId&quot;&#58;&quot;{ListViewId}&quot;&#125;&#125;" />
</Mapping>

Dans l’exemple ci-dessus, le composant WebPart XSLTListView source est mappé à un composant texte moderne (ClientSideText) et à un composant WebPart moderne () :ClientSideWebPart

  • Utilisez l’attribut Order pour déterminer le composant qui apparaît en premier.
  • Pour un composant ClientSideWebPart, spécifiez le Type du composant WebPart. Si vous choisissez le type Custom, spécifiez également la propriété ControlId pour identifier le composant WebPart personnalisé nécessaire.
  • Les propriétés Text, JsonControlData et ControlId peuvent contenir des jetons sous la forme {Token}, qui sont remplacés par des valeurs réelles pendant l’exécution. Chaque jeton défini doit être activé comme propriété de composant WebPart ou comme résultat de la fonction, comme expliqué précédemment.

Définition des éléments AddOns dans le modèle de transformation de page

Les modules complémentaires (AddOns) vous permettent d’insérer votre logique personnalisée dans le modèle de mappage en suivant ces 2 étapes :

  • Créer un assembly personnalisé qui héberge vos fonctions/sélecteurs personnalisés
  • Déclarer cet assembly personnalisé dans les éléments AddOns

Créer un assembly fonctions/sélecteurs personnalisé

Pour créer vos propres fonctions, référencez l’assembly SharePoint.Modernization.Framework dans votre projet, puis créez une classe qui hérite de la classe SharePointPnP.Modernization.Framework.Functions.FunctionsBase :

using Microsoft.SharePoint.Client;
using SharePointPnP.Modernization.Framework.Functions;
using System;

namespace Contoso.Modernization
{
    public class MyCustomFunctions: FunctionsBase
    {
        public MyCustomFunctions(ClientContext clientContext) : base(clientContext)
        {
        }

        public string MyListAddServerRelativeUrl(Guid listId)
        {
            if (listId == Guid.Empty)
            {
                return "";
            }
            else
            {
                var list = this.clientContext.Web.GetListById(listId);
                list.EnsureProperties(p => p.RootFolder.ServerRelativeUrl);
                return list.RootFolder.ServerRelativeUrl;
            }
        }

    }
}

Déclarer un assembly personnalisé

Avant d’utiliser les fonctions personnalisées, elles doivent être déclarées dans le modèle en ajoutant une référence par bibliothèque/classe dans l’élément AddOns :

<AddOn Name="Custom" Type="Contoso.Modernization.MyCustomFunctions" Assembly="Contoso.Modernization.dll" />

ou (notez le chemin d’accès complet)

<AddOn Name="Custom" Type="Contoso.Modernization.MyCustomFunctions" Assembly="c:\transform\Contoso.Modernization.dll" />

Notez que chaque déclaration porte un nom (« Custom » dans l’exemple ci-dessus).

Utiliser les fonctions/sélecteurs personnalisés

Une fois l’assembly défini, vous pouvez utiliser vos fonctions et sélecteurs en les référençant par leur nom (par exemple, par le préfixe « Custom » dans l’exemple ci-dessous) :

<Property Name="ListId" Type="guid" Functions="{ListServerRelativeUrl} = Custom.MyListAddServerRelativeUrl({ListId})"/>