Kolumne: SharePoint ganz praktisch

SharePoint: so funktioniert clientseitiges Rendering mit JavaScript – Teil 2
Keine Kommentare

Wie im ersten Teil dieses Artikels verdeutlicht wurde, bieten clientseitige Ausgabevorlagen eine gute Alternative zu serverseitigen Steuerelementen. Wie auch serverseitige Elemente ermöglichen CSR-Vorlagen die Beeinflussung der Oberflächendarstellung. Die heutige Ausgabe stellt weitere Anpassungsmöglichkeiten sowie einige zusätzliche Techniken vor.

Clientseitige Ausgabevorlagen können für unterschiedliche SharePoint-Oberflächenelemente definiert werden. Aktuell unterstützt SharePoint clientseitige Ausgabevorlagen für die folgenden Bereiche:

  • List Views
  • Formulare (Neu, Bearbeiten, Datenanzeige)
  • Suchergebnisse

Zu beachten ist hierbei, dass nicht alle Bereiche des SharePoint-UI über clientseitige Ausgabevorlagen angepasst werden können. In diesen Fällen muss dann auf die klassische serverseitige Anpassung – per Code oder über XSLT – zurückgegriffen werden. Wenn dies keine Option ist, kann die HTML-Oberfläche auch per JavaScript/jQuery direkt angepasst werden. Um das dazu notwendige JavaScript zu laden, kann auch die in der letzten Ausgabe erläuterte JSLink-Eigenschaft verwendet werden. Mittels dieser Eigenschaft kann auf einfache Art und Weise eine zusätzliche JavaScript-Referenz eingebunden werden. Besonders zu beachten ist hierbei, dass auch mehrere Skriptreferenzen darüber eingebunden werden können. Die URLs zu den einzelnen Skriptdateien müssen dabei einfach durch ein Pipe-Zeichen (|) voneinander separiert angegeben werden.

Formulare im Lesemodus

In der letzten Ausgabe wurde bereits demonstriert, wie auf die Darstellung eines Felds innerhalb einer Liste Einfluss genommen werden kann. Neben der Anpassung von Listendarstellungen können aber auch Formulare clientseitig angepasst werden. Damit die eigenen clientseitigen Vorlagen bei einem SharePoint-Listenformular auch berücksichtigt werden, muss die richtige Ausgabeart gesetzt werden. SharePoint-Listenformulare unterscheiden hierbei zwischen drei verschiedenen Ausgabemöglichkeiten (Abb. 1):

  • Standard (StandardLayout)
  • Server Render
  • Custom (CSRCustomLayout)
Abb. 1: Auswahl des Ausgabemechanismus

Abb. 1: Auswahl des Ausgabemechanismus

Bei der 2. Einstellung „Server Render“ erfolgt die Generierung der Darstellung wieder auf der Seite des Servers unter Zuhilfenahme des altbekannten XSLT-Mechanismus. Die verbleibenden zwei Einstellungen verwenden hingegen den neuen clientseitigen Mechanismus. Bei der ersten CSR-Wahl bleibt der allgemeine Aufbau des Formulars erhalten. Diese Option ist gut anwendbar, wenn nur einzelne dedizierte Felder bei der Ausgabe angepasst werden sollen. Dazu zeigt Abbildung 2 ein entsprechendes Beispiel. Hier wurden lediglich die Ausgaben der Felder für Name und Titel clientseitig angepasst. Das Label und die Positionierung innerhalb des Formulars bleiben hierbei vollständig erhalten. Wie erkennbar ist, wurde die Ausgabe des Felds Name in eine Schaltfläche verwandelt. Beim Klick auf die Schaltfläche greift ein neues JavaScript und öffnet die Datei. Die Ausgabe der Titelspalte wurde ebenfalls angepasst, diese wird nun als Überschrift (h2) ausgegeben. In Listing 1 ist das umgesetzte CSR-Skript dargestellt. Abbildung 3 zeigt das so entstandene neue HTML in der Firefox-Konsole. Intern generiert dieser Ausgabemechanismus zunächst für jedes Feld einen Platzhalter in Form eines span-Tags mit einem eindeutigen ID-Wert als Kennung. Nachdem diese Ausgabe über die eingebaute Methode RenderForm erfolgt ist, sorgt der CSR-Mechanismus für die Ersetzung der Platzhalter mit dem definierten neuen HTML. Konkret übernimmt dies die Methode RenderReplace, die für den internen Ersetzungsmechanismus zuständig ist. Da hierbei das allgemeine Layout des Formulars nicht verändert wird, werden auch nicht die eigenen Ausgabemethoden für z. B. den Kopf- oder Fußbereich aufgerufen. Diese Methoden werden bei dieser Ausgabeart ignoriert.

Abb. 2: Eigenes Ausgabeformat für ein Formularfeld

Abb. 2: Eigenes Ausgabeformat für ein Formularfeld

Abb. 3: Durch die CSR-Vorlage generiertes HTML

Abb. 3: Durch die CSR-Vorlage generiertes HTML

(function () {
  var overrideCtx = {};
  overrideCtx.Templates = {};
  overrideCtx.Templates.Fields = {
    "Title": {
      "DisplayForm": renderViewTitle
    },
    "FileLeafRef": {
      "DisplayForm": renderViewUrl
    }
  }
  SPClientTemplates.TemplateManager.RegisterTemplateOverrides(overrideCtx);
})();

function renderViewTitle(ctx) {
  return '<h2>' + ctx.CurrentItem.Title + '</h2>';
}
function renderViewUrl(ctx) {
  return "<input type='button' value='Anzeigen: " + ctx.CurrentItem.FileLeafRef.BaseName + "' onclick='javascript:location.href=\"" + ctx.CurrentItem.FileLeafRef.FileUrl + "\"' />";
}

Formulare im Bearbeitungsmodus

Das vorherige Beispiel hat die Anpassung des Formulars für den reinen Anzeigemodus demonstriert. Dies ist in der Regel sehr einfach, da keine Interaktion mit den Daten möglich ist. Über CSR-Vorlagen kann aber auch die Darstellung im Bearbeitungs- bzw. Anlagemodus angepasst werden. Dies ist in der Regel mit etwas mehr Aufwand verbunden, da hier der Benutzer mit den Daten interagieren muss. Abbildung 4 zeigt das Ergebnis der nächsten Erweiterung. Hier wurde das Feld Titel um eine Autovervollständigung erweitert. Zur Veranschaulichung wurde hier nur das Bearbeitungsformular angepasst, analog dazu ist aber auch das Formular für die Neuanlage anpassbar. Listing 2 zeigt das umgesetzte JavaScript für diesen Ausbau. Um das Feld innerhalb des Bearbeitungsformulars anpassen zu können, muss eine entsprechende Render-Funktion beim Edit Form definiert werden. In diesem Fall handelt es sich um die renderEditTitle-Funktion. Zunächst ermittelt diese Funktion den internen Namen des Felds und generiert damit einen eindeutigen Feldidentifizier, der in der Variablen ctlID gespeichert wird. Um nach der Erstellung des Felds zusätzliche Ereignisse oder auch Erweiterungen (Plug-ins) an das Steuerelement binden zu können, kann über die Methode registerInitCallback eine Rückruffunktion registriert werden. Innerhalb der Rückruffunktion wird nun zunächst die Bibliothek Awesomplete für die Autovervollständigung registriert. Um das Beispiel übersichtlich zu halten, kommen die Vorschlagswerte hier aus einem statischen Array.

Weiterhin wird das Änderungsereignis (Change Event) registriert, um Änderungen direkt in das Feld zurückzuschreiben. Am Ende wird das eigentliche HTML-Markup für die Felddarstellung zusammengesetzt und zurückgegeben. Zu beachten ist hier, dass keinerlei weitere Bibliotheken, wie zum Beispiel jQuery, notwendig sind. Lediglich die zusätzliche JavaScript-Bibliothek für die Autovervollständig muss eingebunden werden. Dies geht ebenfalls sehr einfach über die JSLink-Eigenschaft des Web Parts, da hier – wie weiter oben bereits erwähnt wurde – mehrere Skriptreferenzen separiert per Pipe-Symbol (|) angegeben werden können. Damit das eigene CSR-Script und die Awesomplete-Bibliothek auch beim Bearbeiten eines Eintrags geladen werden, muss das zugehörige Web Part der Bearbeitungsseite entsprechend konfiguriert werden. Dazu muss man auf die Bearbeitungsseite wechseln und die Seite selbst in den Bearbeitungsmodus setzen. Danach die Web-Part-Eigenschaften der Listenbearbeitung öffnen und die JSLink-Eigenschaft setzen. Damit auch das Design der Autovervollständigung vernünftig aussieht, muss noch die CSS-Datei der Awesomplete-Bibliothek eingebunden werden. Dafür wurde der Seite ein Skripteditor-Web Part hinzugefügt. Dieses Web Part fügt der Seite den Link zur CSS-Datei hinzu.

Abb. 4: Eingabefeld funktional um Vorschlagswerte erweitern

Abb. 4: Eingabefeld funktional um Vorschlagswerte erweitern

(function () {
  var overrideCtx = {};
  overrideCtx.Templates = {};
  overrideCtx.Templates.Fields = {
    "Title": {
      "DisplayForm": renderViewTitle,
      "EditForm": renderEditTitle
    },
    "FileLeafRef": {
      "DisplayForm": renderViewUrl
    }
  }
  SPClientTemplates.TemplateManager.RegisterTemplateOverrides(overrideCtx);
})();
function renderEditTitle(ctx) {
  var staticName = ctx.CurrentFieldSchema.Name;
  var ctlID = staticName + "_control";

  ctx.FormContext.registerInitCallback(staticName, function () {
    var awesomplete = new Awesomplete($get(ctlID));
    awesomplete.list = ["Ada", "Java", "JavaScript", "Brainfuck", "LOLCODE", 
      "Node.js", "Ruby on"];
      $addHandler($get(ctlID), "change", function (e) {
      ctx.FormContext.updateControlValue(staticName, $get(ctlID).value);
    });
  });
  return String.format('<input type="text" id="{0}" name="{0}" value="{1}" />', 
    ctlID, ctx.CurrentItem.Title);
}

Allgemeine Formulardarstellung anpassen

In den letzten beiden Beispielen wurden Anpassungen für bestimmte Formularfelder vorgenommen. Teilweise besteht aber auch die Anforderung, das Layout des Formulars an weiteren Stellen anpassen zu müssen. In diesem Fall reicht der einfache Darstellungsmodus „Standard (StandardLayout)“ nicht mehr aus. Damit der Formularaufbau beeinflusst werden kann, muss der zweite clientseitige Ausgabemechanismus „Custom (CSRCustomLayout)“ gewählt werden. Nur in diesem Modus kann dann über das CSR-Script die Formulardarstellung an weiteren Stellen beeinflusst werden. Allerdings scheint es jedoch so, dass dieser Modus bisher noch nicht offiziell unterstützt wird. Schaltet man in diesen Modus, ohne eigene Anpassungen vorgenommen zu haben, erscheint ein Formular, in dem schon alle Feldanordnungen nicht mehr korrekt sind. Mit viel Aufwand gelingt es zwar wieder, die ursprüngliche Darstellung herzustellen, allerdings ist das nicht ganz einfach und zudem sehr fehleranfällig. Aus diesem Grund zeigt das Beispiel in Listing 3 auch nur die Möglichkeit, wie in diesem Modus eigene Kopf- und Fußbereiche generiert werden können.

(function () {
  var overrideCtx = {};
  overrideCtx.Templates = {};
  overrideCtx.Templates.Header = function (ctx) {
    return "<h1>Eigener Kopfbereich!</h1>"
  }
  overrideCtx.Templates.Footer = function (ctx) {
    return "<h1>Eigener Fussbereich!</h1>"
  }
  SPClientTemplates.TemplateManager.RegisterTemplateOverrides(overrideCtx);
})();

Einbindung von Ressourcen

Neben dem eigenen JavaScript-Code werden oft auch noch zusätzliche Ressourcen zur Laufzeit benötigt. Typischerweise handelt es sich dabei meist um zusätzliche Bibliotheken oder CSS-Dateien mit Layoutdefinitionen. Wie weiter oben schon gezeigt wurde, können benötigte JavaScript-Bibliotheken direkt über die JSLink-Eigenschaft eingebunden werden. Der wesentliche Nachteil dieser Variante ist jedoch, dass hierbei die definierten Skriptreferenzen immer geladen werden. Das heißt, wird zum Beispiel jQuery über diesen Weg eingebunden, besteht die Gefahr, dass die Bibliothek eventuell schon über die Master Page eingebunden wurde. Somit würde die Bibliothek mehrfach geladen, und das könnte Probleme nach sich ziehen. Aus diesem Grund ist eine dynamische Einbindung der statischen Einbindung vorzuziehen. Dies ist auch nicht kompliziert, wie es in Listing 4 für die Einbindung von jQuery demonstriert wird. Listing 4 zeigt außerdem, wie benötigte CSS-Definitionen direkt in der CSR-Vorlage definiert werden können. Die Hilfsfunktion MultiString gibt einen gültigen CSS-Definitionsblock zurück, der in der Variablen customCSS abgelegt wird. Die Funktion InitOnPreRender fügt diesen CSS-Block der Seite über jQuery hinzu. Die Funktion InitOnPreRender selbst ist dem Vorlagen-Handler OnPreRender zugeordnet und wird somit von der CSR-Vorlage zum passenden Zeitpunkt aufgerufen. Diese Form in der Einbindung eignet sich jedoch nur, wenn die benötigten CSS-Definitionen nicht zu umfangreich sind. Umfangreiche CSS-Anweisungen sollten weiterhin über eine externe Datei eingebunden werden. Hierzu kann über jQuery ein <link>-Tag erstellt werden, das dynamisch dem head-Tag hinzugefügt wird.

var runOnce=true;
var MultiString = function (f) {
  return f.toString().split('\n').slice(1, -1).join('\n');
}
var customCSS = MultiString(function () {/**
body {
  background-color: #ccc;
}
**/
});
(function () {
  (window.jQuery || document.write('<script src="//ajax.aspnetcdn.com/ajax/ 
    jquery/jquery-1.10.0.min.js"><\/script>'));
  var overrideCtx = {};
  overrideCtx.Templates = {};
  overrideCtx.OnPreRender = InitOnPreRender;
  SPClientTemplates.TemplateManager.RegisterTemplateOverrides(overrideCtx);
})();
function InitOnPreRender(ctx) {
  if (runOnce) {
    runOnce=false;    
    jQuery(document).ready(function () {
      jQuery("#WebPart" + ctx.FormUniqueId).prepend("<style>" + customCSS + 
        "</style>");
    });
  }
}

Minimal Download Strategy (MDS)

Bei dem Feature „Minimal Download Strategy” (kurz: MDS) handelt es sich um eine Neuerung in SharePoint 2013. Dieses neue Feature verbessert die Ladezeit von Seiten, indem nur geänderte Bereiche partiell aktualisiert werden. Dieser Mechanismus kann allerdings teilweise dazu führen, dass eigene dynamische Anpassungen an der Seite verloren gehen. Die Gefahr besteht auch bei CSR-Vorlagen, da die bisherigen Beispiele nur beim initialen Laden der Seite ausgeführt werden. Das heißt, wird die Seite mit einer eigenen CSR-Definition zum ersten Mal geladen, funktioniert alles wie erwartet. Wird dann aber von der Seite weg navigiert und später wieder zurück, wird das Skript unter Umständen nicht mehr ausgeführt, und die eigene Darstellung geht verloren. Dies liegt in der Arbeitsweise des MDS-Features zugrunde, da hierbei nur Teile der Seite aktualisiert werden. Das zweite Problem ist die eingebaute Garbage Collection im MDS-Mechanismus. Diese sorgt dafür, dass Variablen – die am window-Objekt deklariert wurden – entfernt werden. Dies ist sinnvoll, da ansonsten durch das teilweise Laden von Seiten zu viel Speicherplatz gebunden wird. Um sicherzustellen, dass dies für das eigene CSR-Script nicht zum Problem führt, gibt es eine einfache Lösung. Dazu muss lediglich das Skript in einem Namensraum registriert werden. Wie die beiden beschriebenen Probleme dann konkret gelöst werden können, ist in Listing 5 zu sehen. Hier wird zunächst über die erste Anweisung ein Namensraum registriert, in dem alle weiteren Funktionen und Variablen definiert werden. Diese Vorgehensweise ist – auch wenn das MDS-Problem nicht zutrifft – zu empfehlen. Danach werden in den verschiedenen Namensräumen Funktionen definiert. Innerhalb des Fields-Objekts erfolgt dann wiederum die Konfiguration des CSR-Script-Objekts. Um nun das Problem des Skriptaufrufs auch bei einer MDS-Navigation zu lösen, wird über den Aufruf RegisterModuleInit das Skript an eine Ereignismethode gebunden. Diese ruft das angegebene Skript auch bei einem partiellen Seitenaufruf auf. Somit sind nun beide potenziellen Fehlerquellen berücksichtigt worden.

Type.registerNamespace("DevSky");
DevSky.SPSKolumne = DevSky.SPSKolumne || {};
DevSky.SPSKolumne.Templates = DevSky.SPSKolumne.Templates || {}
DevSky.SPSKolumne.Functions = DevSky.SPSKolumne.Functions || {}

DevSky.SPSKolumne.Functions.RenderColorField = function (ctx) {
  var currentValue = ctx.CurrentItem.Title
  return "<span style='background-color : " + currentValue + "' >
    </span>" + currentValue;
}
DevSky.SPSKolumne.Templates.Fields = {
  'Title': {
    'DisplayForm': DevSky.SPSKolumne.Functions.RenderColorField,
    'View': DevSky.SPSKolumne.Functions.RenderColorField,
    'NewForm': null,
    'EditForm': null
  }
}
DevSky.SPSKolumne.Functions.RegisterField = function () {
  
  SPClientTemplates.TemplateManager.RegisterTemplateOverrides(DevSky.SPSKolumne);
 RegisterModuleInit("/_layouts/15/devsky/form-csr.js", DevSky.SPSKolumne);
}
DevSky.SPSKolumne.Functions.RegisterField();

Zusammenfassung

Wie gezeigt wurde, können über CSR-Scripte weitreichende Änderungen an der Standard-SharePoint-Oberfläche durchgeführt werden. In vielen Fällen kann somit auf serverseitigen Code gut verzichtet werden. Im Vergleich zu serverseitigen Lösungen sind CSR-Vorlagen flexibler und leichter anpassbar, und der Installationsaufwand ist geringer. Die nächste Ausgabe der SharePoint-Kolumne widmet sich Anzeigevorlagen, über die ebenfalls eine clientseitige Anpassung der Darstellung realisiert werden kann.


Aufmacherbild: Close-up Of A Businessman Filling Survey Form Online via Shutterstock / Urheberrecht: Andrey_Popov

Windows Developer

Windows DeveloperDieser Artikel ist im Windows Developer erschienen. Windows Developer informiert umfassend und herstellerneutral über neue Trends und Möglichkeiten der Software- und Systementwicklung rund um Microsoft-Technologien.

Natürlich können Sie den Windows Developer über den entwickler.kiosk auch digital im Browser oder auf Ihren Android- und iOS-Devices lesen. In unserem Shop ist der Windows Developer ferner im Abonnement oder als Einzelheft erhältlich.

Unsere Redaktion empfiehlt:

Relevante Beiträge

Hinterlasse einen Kommentar

Hinterlasse den ersten Kommentar!

avatar
400
  Subscribe  
Benachrichtige mich zu:
X
- Gib Deinen Standort ein -
- or -