SERIE: IL CLIENT SIDE RENDERING DI SHAREPOINT 2013


Siamo quasi alla fine della serie e, come promesso, oggi vedremo le tecniche che abbiamo a disposizione per installare i nostri display template all'interno di SharePoint in maniera automatica.
Come abbiamo visto nei precedenti post, per fare in modo che il motore del Client Side Rendering di SharePoint 2013 applichi il nostro display template a liste o campi, è necessario valorizzare la proprietà JSLink con l'URL del file Javascript contenente la definizione del display template. Vi ricordo che la proprietà JSLink è stata aggiunta in tutte le web part di default di SharePoint.
Effettuare questa operazione a mano è sicuramente la via giusta se abbiamo scritto un display template per una specifica esigenza (es: per una specifica lista), mentre risulta un'operazione veramente scomoda se va fatta su più liste e totalmente impensabile se vogliamo fare in modo che ogni lista creata con un particolare template venga configurata con il nostro display template.

Provisioning tramite Server Object Model

Bene, vediamo una prima tecnica che abbiamo a disposizione. Questa prima tecnica sfrutta il Server Object Model di SharePoint 2013 per installare in automatico un display template all'interno di tutte le viste e tutte le form di una specifica lista.
Ho deciso di inserire questo codice all'interno di una farm solution, contenente sia un feature receiver che gli oggetti necessari al provisioning di una lista (nel mio caso sempre una lista di task).

Ecco il codice del feature eceiver.

public class ProvisioningEventReceiver : SPFeatureReceiver
{
     private const string JS_LINK_URL = "~sitecollectionlayouts/D4S/Scripts/TaskPercentComplete.js";

    public override void FeatureActivated(SPFeatureReceiverProperties properties
    {            
         SPWeb web = properties.Feature.Parent as SPWeb;
         if (web != null)
         {
             SPList list = web.GetList("Lists/MyTasks");

             UpdateListForm(list.Forms[PAGETYPE.PAGE_EDITFORM].Url, web);
             UpdateListForm(list.Forms[PAGETYPE.PAGE_NEWFORM].Url, web);
             UpdateListForm(list.Forms[PAGETYPE.PAGE_DISPLAYFORM].Url, web);

             for (int i = 0; i < list.Views.Count; i++)
             {
                 SPView view = list.Views[i];
                 view.ViewFields.Add("PercentComplete");
                 view.JSLink = JS_LINK_URL;
                 view.Update();
             }
         }
     }

     private void UpdateListForm(string url, SPWeb web)
     {
         SPLimitedWebPartManager webPartManager = web.GetLimitedWebPartManager(url, System.Web.UI.WebControls.WebParts.PersonalizationScope.Shared);
         ListFormWebPart formWebPart = webPartManager.WebParts[0] as ListFormWebPart;
         if (formWebPart != null)
         {
             formWebPart.JSLink = JS_LINK_URL;
             webPartManager.SaveChanges(formWebPart);
         }
     }
}

Come potete vedere, abbiamo prima aggiornato la proprietà JSLink delle web part presenti all'interno delle form di modifica, inserimento e visualizzazione, sfruttando le classi SPLimitedWebPartManager e ListFormWebPart. Poi abbiamo valorizzato la medesima proprietà su tutte le viste della nostra lista di task, sfruttando la classe SPView.
Ovviamente il codice che abbiamo visto in questo esempio, lo possiamo riutilizzare per preparare uno script PowerShell utile ai nostri scopi.


Provisioning tramite CAML

La seconda tecnica che abbiamo a disposizione vede la modifica del codice CAML che solitamente utilizziamo per fare il provisioning dei nostri template di lista.
Questa fa in modo che ogni volta che un utente crea un nuova lista utilizzando il nostro template di lista, quest'ultima risulti già configurata con il display template pronto per essere dato in pasto al motore del Client Side Rendering.
Per mettere in pratica questa tecnica non dovete far altro che creare un nuovo list template tramite Visual Studio (New element > List), selezionare la voce "Create a customizable list template and a list instance of it", aprire il file Schema.xml e valorizzare l’elemento <JSLink /> di ogni elemento <View /> che è a rappresentare una singola vista che verrà creata assieme alla relativa lista.
Ecco un esempio di codice:

<View BaseViewID="1" Type="HTML" WebPartZoneID="Main" DisplayName="$Resources:core,objectiv_schema_mwsidcamlidC24;" DefaultView="TRUE" MobileView="TRUE" MobileDefaultView="TRUE" SetupPath="pages\viewpage.aspx" ImageUrl="/_layouts/15/content/images/generic.png?rev=23" Url="AllItems.aspx">
   <Toolbar Type="Standard" />
   <XslLink Default="TRUE">main.xsl</XslLink>
   <JSLink>~sitecollectionlayouts/D4S/Scripts/CustomContentTypeRendering.js</JSLink>
   <RowLimit Paged="TRUE">30</RowLimit>
   <ViewFields>          
       <FieldRef Name="LinkTitle"></FieldRef>
   </ViewFields>
   <Query>
      <OrderBy><FieldRef Name="ID"></FieldRef></OrderBy>
   </Query>
   <ParameterBindings>
     <ParameterBinding Name="NoAnnouncements" Location="Resource(wss,noXinviewofY_LIST)" />
     <ParameterBinding Name="NoAnnouncementsHowTo" Location="Resource(wss,noXinviewofY_DEFAULT)" />
   </ParameterBindings>
</View>

Nota bene: la proprietà JSLink è presente anche all'interno della definizione dell’elemento <ContentType />. Purtroppo però, specificando la URL del file Javascript contenente il display template, questo viene ignorato dal sistema di provisioning di liste di SharePoint. 
Come potete ben capire questo è davvero un peccato, perché poteva risultare sicuramente molto utile legare un display template ad un Content Type.
Ecco quindi il codice che NON funziona:

<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
   <!-- QUESTO LINK NON VIENE PRESO!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!-->
  <ContentType ID="0x0100EBFEC1154AB94CDB82A0E138287E8B5E"
               Name="Custom content type"
               Group="Dev4Side"
               Description=""
               Inherits="TRUE"
               JSLink="~sitecollectionlayouts/D4S/Scripts/CustomContentTypeRendering.js"
               Version="0">
    <FieldRefs>
    </FieldRefs>
  </ContentType>
</Elements>

Potete utilizzare entrambe le tecniche anche all'interno di un'App, per creare applicazioni semplici ma d'effetto utilizzando le funzionalità di default di SharePoint e aggiungendo nuove funzionalità e alzando quella che è la user experience dell'utente finale.
Ovviamente, se decidete di scrivere un'App, dovrete convertire il codice scritto tramite il Server Object Model utilizzando invece le classi del Client Object Model.