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 :
- 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.
- 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.
- 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.
- La dernière étape consiste à créer et configurer la page moderne, puis à y ajouter les composants WebPart modernes mappés.
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="{"serverProcessedContent":{"htmlStrings":{},"searchablePlainTexts":{},"imageSources":{},"links":{}},"dataVersion":"1.0","properties":{"isDocumentLibrary":false,"selectedListId":"{ListId}","listTitle":"{Title}","selectedListUrl":"{ListServerRelativeUrl}","webRelativeListUrl":"{ListWebRelativeUrl}","webpartHeightKey":4,"selectedViewId":"{ListViewId}"}}" />
</Mapping>
<Mapping Name="Library" Default="false">
<ClientSideWebPart Type="List" Order="10" JsonControlData="{"serverProcessedContent":{"htmlStrings":{},"searchablePlainTexts":{},"imageSources":{},"links":{}},"dataVersion":"1.0","properties":{"isDocumentLibrary":true,"selectedListId":"{ListId}","listTitle":"{Title}","selectedListUrl":"{ListServerRelativeUrl}","webRelativeListUrl":"{ListWebRelativeUrl}","webpartHeightKey":4,"selectedViewId":"{ListViewId}"}}" />
</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="{"serverProcessedContent":{"htmlStrings":{},"searchablePlainTexts":{},"imageSources":{},"links":{}},"dataVersion":"1.0","properties":{"isDocumentLibrary":false,"selectedListId":"{ListId}","listTitle":"{Title}","selectedListUrl":"{ListServerRelativeUrl}","webRelativeListUrl":"{ListWebRelativeUrl}","webpartHeightKey":4,"selectedViewId":"{ListViewId}"}}" />
</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 leType
du composant WebPart. Si vous choisissez le typeCustom
, spécifiez également la propriétéControlId
pour identifier le composant WebPart personnalisé nécessaire. - Les propriétés
Text
,JsonControlData
etControlId
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})"/>