pixelconsult

TYPO3 DCE Tutorial

Dynamic Content Elements, kurz DCE, ist eine Extension für die neueren Typo3 Versionen (ab 6.2). Sie arbeitet mit dynamischen Elementen und ersetzt damit die flexiblen Content Elemente, die in TemplaVoila verwendet wurden. Dieses wird seit Typo3 6.2 nicht mehr unterstützt, da Typo3 seitdem verstärkt auf "FLUID" und die dazu gehörenden „View Helper“ setzt. Der große Vorteil der View Helper ist es, das "for-Schleifen" und "if-Abfragen" verwendet werden können.

Mit DCE lassen sich sehr schnell neue Content Elemente anlegen. Durch die Verwendung von Fluid und damit der Bedingungen und Abfragen, lassen sich auch komplizierte Templates schnell anlegen. Ein großer Vorteil ist die getrennte Darstellung von angelegten Eingabe-Elementen und Template. Durch die sehr geordnete und übersichtliche Anzeige der Eingabe-Elemente im Backend ist auch für einen ungelernten Redakteur die Dateneingabe leicht.

Im Großen und Ganzen ist die Extension ziemlich selbsterklärend und für Entwickler, wie auch Redakteure, einfach zu verwenden. 
Wer sich in Fluid-Programmierung auskennt, hat natürlich klare Vorteile. Aber auch für Entwickler, die sich damit noch nicht auskennen, ist sie schnell zu durchschauen.

Problematisch ist leider, dass es (noch) keine ausführliche Dokumentation zu der Extension gibt. Das liegt wohl daran, dass der Entwickler allein ist. Man muss aber sagen, dass er sich viel Mühe gibt und in jedem weiteren Update haben sich schöne neue Funktionen und gute Fixes befunden.

Einfache Erklärungen und kleine Beispiele helfen oft schnell weiter. Da wir die Extension vor einiger Zeit entdeckt haben und uns am Anfang immer nur sehr langsam weiterbewegt haben, da oft nur Kleinigkeiten nicht richtig waren, haben wir uns dazu entschlossen, für alle Interessierten eine kleine Anleitung zu schreiben, wie man mit der Extension umgeht.

Es handelt sich um Beschreibungen und Bilder der Extension-Version 1.3.6.

Tabs

Auf den einzelnen Tabs lassen sich die Eingabe-Elemente für das Backend definieren, die Vorlage für das Frontend festlegen und einige weitere Einstellungen vornehmen.

Tab Allgemein

Auf dem Tab Allgemein wird der Titel des DCEs festgelegt. Hier gibt es auch die Option, den Typ des DCEs zu verändern. Datenbankbasiert ist jedoch die einzige Auswahlmöglichkeit.

Mit Inaktiv lässt sich festlegen, ob das DCE im Backend überhaupt eingesetzt werden darf. Wenn man dieses Auswahlfeld wählt, dann werden alle Instanzen dieses DCEs als ungültig angezeigt.

Eingabefelder

Unter "Felder"lässt sich festlegen, welche Eingabefelder dem Redakteur im Backend angezeigt werden und wie diese aussehen sollen. Wird ein neues Feld erzeugt, so müssen zunächst zwei Felder ausgefüllt werden.

Das erste bestimmt den "Titel dieses Feldes", der dem Redakteur im Backend zu dem Feld angezeigt wird. Im zweiten wird eine, in diesem DCE eindeutige, "Variable"angegeben. Diese wird dazu verwendet, um im Template die Stelle anzugeben, an der die Eingaben des Feldes verwendet werden sollen.

Das Feld kann drei unterschiedliche Typen besitzen: ElementReiter (Tab) oder Abschnitt (Sektion).

Elemente

Ein "Element" kann diverse Konfigurationen zugewiesen bekommen.

Die unten im Bild dargestellten Konfigurationen sind möglich:

TYPE: input

TYPE: text

Vor Version 1.4.5 gibt es die beiden Optionen "Full RTE" und "Inherit RTE from TSconfig". Diese werden ab der Version 1.4.5 in Typo3 Version 7.x.x "Full RTE (7.6)" und "Inherit RTE from TSconfig (7.6)" umgewandelt. Wenn ein Typo3 Version 8.x.x installiert ist, gibt es nur noch das "RTE(8.7)".

  1. <richtextConfiguration>minimal</richtextConfiguration>

TYPE: check

TYPE: select

TYPE: group

TYPE: miscellaneous

TYPE: FAL

Tab

Ein "Tab" erzeugt bei der Dateneingabe im Backend einen neuen Reiter. Alle Elemente oder Sektionen, die unterhalb eines Tabs angeordnet sind werden im Backend auf diesem Tab dargestellt. Es müssen keine Tabs erstellt werden.

Aber sobald ein Tab als erstes im DCE erstellt wird, wird das Standard „Allgemein“ Tab entfernt und durch das benutzerdefinierte ersetzt. Alle weiteren Tabs werden ergänzend hinzugefügt. Wenn nur ein einziges benutzerdefiniertes Tab vorhanden ist, wird dieses im Backend nicht angezeigt. Wichtig ist, dass ein Tab nur angezeigt wird, wenn sich auch ein Element darauf befindet. Ansonsten wird es im Backend ausgeblendet.

Sektion

Eine "Sektion" besteht aus einer Gruppe von beliebigen Elementen.

Im Backend kann die Sektion nicht nur einmal verwendet werden, wie ein Feld, sondern nach Belieben oft. Der Sektion können durch die Schaltfläche "Test" unten immer neue Gruppen von Elementen hinzugefügt werden. Diese lassen sich einzeln löschen und ihre Reihenfolge kann geändert werden.

Tab Template

Auf dem Tab "Template" wird die Darstellung der Eingabe-Felder definiert. Der Code besteht aus Fluid-Programmierung und HTML.

Das Template kann hier einerseits in das Textfeld eingegeben werden und andererseits auch durch eine Datei geladen werden. Dazu wird der Template-Typ von "Inline" auf "Datei" geändert.

Durch einen Klick auf das weiße Feld unter "Template-Inhalt (Fluid)" können die Variablen der vorher definierten Eingabefelder ausgewählt werden. Zusätzlich gibt es noch "Basis-Variablen" und "Viewhelper". Mit Hilfe der Basis-Variablen können zum Beispiel die Seiteneigenschafften ausgewählt werden. Die Viewhelper gehören zur FLUID-Programmierung. Es gibt allgemein verwendete und für die DCEs vom Entwickler geschriebene Helfer. Außerdem ist es auch möglich eigene Viewhelper hinzuzufügen.

Tab DCE-Container

Mit Hilfe des DCE-Containers werden alle Objekte dieses DCEs, die nacheinander im Backend eingefügt werden, in einen Container gelegt. Wie dieser Container aussehen soll, wird in diesem Template definiert. So kann zum Beispiel ein Rahmen definiert werden, in dem dann die Objekte angezeigt werden. Auf diese Weise lässt sich zum Beispiel eine Bilder-Galerie erstellen.Wenn jedoch ein Objekt eines anderen DCEs eingefügt wird, so wird der Container geschlossen. Wird danach wieder ein Objekt des Container-DCEs eingefügt, so wird ein neuer Container eröffnet.

Das Limit gibt an, wie viele Objekte sich in einem Container befinden dürfen. Ein Limit von "0" bedeutet unendlich viele Objekte. Bei einem Limit von zum Beispiel "5" würde nach fünf Objekten der Container geschlossen und für das sechste Objekt ein neuer Container eröffnet. Außerdem lässt sich ein neuer Container eröffnen, indem bei der Eingabe eines neuen Objektes der Haken bei "Neuen DCE-Container bilden" gesetzt wird.

Beispiel

Wenn folgender Code im DCE-Container-Template steht:

  1. <f:section name="main">
  2.   <div class="row">
  3.     <f:render partial="Container/Dces" arguments="{dces:dces}" />
  4.   <div>
  5. </f:section>

Und dann fünf Objekte des Container-DCEs hintereinander im Backend eingefügt werden, dann erscheinen diese alle gemeinsam in einem <div>:

Wird danach ein Objekt eines anderen DCEs eingefügt und dann wieder drei des Container-DCEs, entsteht:

Tab Backend Template

Das "Backend Template" beschreibt, wie gespeicherte Objekte des DCEs im Backend aussehen. Dazu kann einmal der einfache Modus gewählt werden:

Dabei können alle vorhandenen Elemente und Sektionen für die Anzeige ausgewählt werden. Das sieht dann bei einem gespeicherten Objekt dieses DCEs im Backend so aus:

Die zweite Möglichkeit ist ein eigenes Template zu schreiben. Wobei die Art und Weise, wie man dies einbindet sich seit der Version 1.4.0 grundlegend geändert hat. Vor 1.4.0 sah das Ganze so aus:

Oben kann die Überschrift des DCEs definiert werden und unten die Anzeige der Inhaltselemente. Hierzu können HTML und FLUID Codes verwendet werden. Wichtig ist, das der {namespace} aus dem normalen Template übernommen werden muss. Dann können alle Felder, die in diesem DCE definiert sind, eingefügt werden:

  1. {namespace dce=ArminVieweg\Dce\ViewHelpers}
  2.  
  3. <f:image src="fileadmin/img/{field.bild}" width="200" height="auto"/>
  4. <f:format.html>{field.header}</f:format.html>
  5. <f:format.html>{field.text}</f:format.html>

Dieses Template erzeugt dann diese Ansicht bei einem gespeicherten Objekt:

Seit Version 1.4.0 sieht das Eingabefeld nun so aus:

Hier lassen sich nun dieselben Codes verwenden, wie im eigentlichen Template.

Tab Icon & Wizard

Auf diesem Tab kann das Icon ausgewählt werden, mit dem das DCE im Backend angezeigt werden soll. Zusätzlich kann man hier auch bestimmen, ob das DCE überhaupt angezeigt werden soll. Zusätzlich kann die Wizard Kategorie und die Beschreibung bestimmt werden.

Das DCE Icon kann aus einer Reihe von Symbolen ausgewählt werden. Es kann aber auch ein eigenes Icon verwendet werden. Dieses wird dann im Backend angezeigt, wenn ein neues Inhaltselement erzeugt werden soll.

Tab Detailseite

Auf der Detailseite kann man angeben, welche Zusatzinformationen zu einem Objekt angezeigt werden sollen.

Damit dies funktioniert, muss zunächst ein Button im normalen Template untergebracht werden. Dieser lautet zum Beispiel:

  1. <f:link.page additionalParams="{detailDceUid:contentObject.uid}">Weiter</f:link.page>

Durch diesen wird auf der aktuellen Seite die ID dieses speziellen DCE-Objektes aufgerufen und die zusätzlichen Informationen ausgelesen, die sich auf der Detailseite befinden. Mit dem Button:

  1. <f:link.page pageUid="{page.uid}">Zurück</f:link.page>

kann dann wieder zur Original-Seite zurückgekehrt werden.

Beispiel

Wird im Template:

  1. <f:section name="main">
  2.   <div>
  3.     <h1>{field.header}</h1>
  4.     <p>{field.text}</p>
  5.     <f:link.page additionalParams="{detailDceUid:contentObject.uid}">Weiter</f:link.page>
  6.   </div>
  7. </f:section>

und auf der Detailseite:

  1. <f:section name="main">
  2.   <div>
  3.     <h1>{field.header}</h1>
  4.     <p>{field.text}</p>
  5.     <p>Hier gibt es weitere Informationen</p>
  6.     <f:link.page pageUid="{page.uid}">Zurück</f:link.page>
  7.   </div>
  8. </f:section>

definiert, dann erhält man zunächst:

Nach einem Klick auf "Weiter" ändert sich die Seite zu:

Tab Sonstiges

Hier kann man definieren welche Tabs und Paletten-Felder, wie zum Beispiel Sprache, im Backend dargestellt werden sollen.

Konfigurationen

Wenn direkt aus dem Dropdown Feld „Konfigurationen“ ausgewählt wird, wird immer die Standard-Konfiguration angezeigt. Diese kann einfach so verwendet oder aber verändert werden.

TYPE:input

Mit Hilfe eines "simple input field" lässt sich auch eine automatische Datumsauswahl erzeugen. Dafür wird einfach das <eval>trim</eval> mit einem <eval>date</eval> ersetzt

  1. <config>
  2.   <type>input</type>
  3.   <size>30</size>
  4.   <eval>date</eval>
  5. </config>

Das ergibt dann folgende Ansicht im Backend:

Um diese Eingabe dieses Feldes im Frontend ausgeben zu können muss der date-ViewHelper verwendet werden. Dieser lautet:

  1. <f:format.date>{field.datum}</f:format.date>

Das Ergebnis ist dann: "22-02-17".

Um das Datum in eine andere Form zu bringen, kann man auch verwenden:

  1. <f:format.date date="{field.datum}" format="y-m-d" />

Das Ergebnis lautet dann: "17-02-22".

TYPE:check

Auch bei einer Checkbox können weitere Felder hinzugefügt und sogar mit <cols> in einer Zeile angezeigt werden. Dazu wird der ursprüngliche Code wie folgt erweitert:

  1. <config>
  2.   <type>check</type>
  3.   <items type='array'>
  4.     <numIndex index='0' type='array'>
  5.       <numIndex index='0'>Label A</numIndex>
  6.       <numIndex index='1'>0</numIndex>
  7.     </numIndex>
  8.     <numIndex index='1' type='array'>
  9.       <numIndex index='0'>Label B</numIndex>
  10.       <numIndex index='1'>1</numIndex>
  11.     </numIndex>
  12.     <numIndex index='2' type='array'>
  13.       <numIndex index='0'>Label B</numIndex>
  14.       <numIndex index='1'>2</numIndex>
  15.     </numIndex>
  16.   </items>
  17.   <minitems>0</minitems>
  18.   <maxitems>3</maxitems>
  19.   <cols>3</cols>
  20. </config>

TYPE:select

Die "Automatical list of items" zeigt, wenn man die Standard Konfiguration nicht verändert, eine Liste aller vorhandenen Unterseiten in der Reihenfolge ihrer Seiten-Ids. Wenn man die angezeigte Reihenfolge in die im Seitenbaum angezeigte ändern will, oder bestimmen will, welche Unterseiten angezeigt werden, muss die Konfiguration um folgendes ergänzt werden:

  1. <foreign_table_where>AND pages.pid = 5 ORDER BY pages.sorting</foreign_table_where>

 Wenn man die Konfiguration zu

  1. <config>
  2. <type>select</type>
  3. <foreign_table>pages</foreign_table>
  4. <renderType>selectMultipleSideBySide</renderType>
  5. <minitems>0</minitems>
  6. <maxitems>10</maxitems>
  7. <config>

 ändert, dann wechselt die Ansicht der Auswahl wie folgt:

Wenn nun die Konfiguration noch um

  1. <multiple>1</multiple>

erweitert wird, können Elemente mehrfach ausgewählt werden.

 

Mit Hilfe von

  1. <enableMultiSelectFilterTextfield>1</enableMultiSelectFilterTextfield>

Kann zum rechten Auswahlfeld eine dynamische Suche hinzugefügt werden:

Eine weitere Auswahlansicht ist

  1. <renderType>selectCheckBox</renderType>

Mit dem Ergebnis:

Außerdem gibt es noch eine Baumansicht:

  1. <config>
  2.   <type>select</type>
  3.   <renderType>selectTree</renderType>
  4.   <foreign_table>pages</foreign_table>
  5.   <treeConfig>
  6.     <parentField>pid</parentField>
  7.     <appearance>
  8.       <expandAll>1</expandAll>
  9.     </appearance>
  10.   </treeConfig>
  11.   <maxitems>5</maxitems>
  12. </config>

Diese lässt sich mit:

  1. <rootUid>5</rootUid>

direkt unter <parentField> auf die ID einer Unterseite beschränken.

 

Soll bei der "Manuel list of items" das erste, standardmäßig ausgewählte Element leer sein, dann muss in der Konfiguration das erste Label leer bleiben. Zum Beispiel, wenn man die Header-Ebene auswählen möchte, dann sieht die Konfiguration wie folgt aus:

  1. <config>
  2.   <type>select</type>
  3.   <items type='array'>
  4.     <numIndex index='0' type='array'>
  5.       <numIndex index='0'</numIndex>
  6.       <numIndex index='1'>0</numIndex>
  7.     </numIndex>
  8.     <numIndex index='1' type='array'>
  9.       <numIndex index='0'>H1</numIndex>
  10.       <numIndex index='1'>1</numIndex>
  11.     </numIndex>
  12.     <numIndex index='2' type='array'>
  13.       <numIndex index='0'>H2</numIndex>
  14.       <numIndex index='1'>2</numIndex>
  15.     </numIndex>
  16.     <numIndex index='3' type='array'>
  17.       <numIndex index='0'>H3</numIndex>
  18.       <numIndex index='1'>3</numIndex>
  19.     </numIndex>
  20.   </items>
  21.   <size>1</size>
  22.   <minitems>1</minitems>
  23.   <maxitems>1</maxitems>
  24. </config>

Das ergibt dann im Backend folgende Ansicht:

Bis auf die Baum-Ansicht können auch hier alle <renderType> verwendet werden.

 

Möchte man zu jedem der Elemente der manuellen Liste ein Bild oder Icon hinzufügen, so ist dies möglich durch:

  1. <numIndex index="1" type="array">
  2.   <numIndex index="0">Layout 1</numIndex>
  3.   <numIndex index="1">1</numIndex>
  4.   <numIndex index="2">EXT:dce/layout1.jpg</numIndex>
  5. </numIndex>

Das entsprechende Bild muss im Ordner "typo3conf/ext/dce" vorhanden sein. Bei dem Standard-<renderType> müssen für alle Elemente Bilder angegeben werden. Dann ergibt dies folgende Ansicht:

Sollen die Icons auch unter der Auswahl angezeigt werden, muss folgende Zeile hinzugefügt werden:

  1. <showIconTable>1</showIconTable>

Wenn man

  1. <renderType>selectCheckBox</renderType>

verwendet, dann kann auch noch eine Beschreibung (description) hinzufügen mit Hilfe von:

  1. <numIndex index="1" type="array">
  2.   <numIndex index="0">Layout 1</numIndex>
  3.   <numIndex index="1">1</numIndex>
  4.   <numIndex index="2">EXT:dce/layout1.jpg</numIndex>
  5.   <numIndex index="3">Beschreibung</numIndex>
  6. </numIndex>

Das sieht wie folgt aus:

TYPE:group

Wird "File upload" ausgewählt, dann sieht die Standard-Konfiguration wie folgt aus:

  1. <config>
  2.   <type>group</type>
  3.   <internal_type>file</internal_type>
  4.   <allowed>jpg,jpeg,png,gif</allowed>
  5.   <size>1</size>
  6.   <minitems>0</minitems>
  7.   <maxitems>1</maxitems>
  8.   <uploadfolder>uploads/pics</uploadfolder>
  9.   <show_thumbs>1</show_thumbs>
  10. </config>

Dadurch wird die im Backend ausgewählte Datei zu dem Ordner "uploads/pics" hinzugefügt. Jede erneute Auswahl des Bildes fügt das Bild wieder zu diesem Ordner hinzu und versieht es hinten mit einer fortlaufenden Nummer. Dadurch ist die Verwaltung der Bilder relativ schwer und sie lassen sich nicht so einfach ersetzen, da das Bild an jeder Stelle von Hand ausgetauscht werden muss. Man kann den Ordner natürlich ändern, aber auch entfernen. Dazu löscht man die gesamte Zeile <uploadfolder>. Dann wird keine neue Datei erzeugt, sondern direkt die Datei aus dem Backend verwendet. Es wird jedoch keine Verknüpfung auf die Datei gelegt. Das bedeutet, sie kann ohne Fehlermeldung über das Backend gelöscht werden und kann dann im Frontend nicht mehr angezeigt werden.

 

Mit Hilfe von "Link Pages and get pages as associative array" kann eine Reihe von Bildern schnell eingebunden werden. Benötigt wird dazu eine "Dateisammlung", wie sie Backend von Typo3 erzeugt werden kann. Die Konfiguration für dieses Element wird wie folgt geändert:

  1. <config>
  2.   <type>group</type>
  3.   <internal_type>db</internal_type>
  4.   <allowed>sys_file_collection</allowed>
  5.   <size>5</size>
  6.   <minitems>0</minitems>
  7.   <maxitems>999</maxitems>
  8.   <show_thumbs>1</show_thumbs>
  9.   <dce_load_schema>1</dce_load_schema>
  10. </config>

TYPE:miscellaneous

Wenn unter Konfiguration die „Display Conditions“ ausgewählt werden erhält man nur:

  1. <displayCond>FIELD:settings.relatedField:=:1</displayCond>

Dabei wird abgefragt, ob in einem Auswahlfeld eine bestimmte Auswahl getroffen wurde. Will man mehrere überprüfen, so benötigt man für eine Oder-Abfrage (OR):

  1. <displayCond>
  2.   <OR>
  3.     <numIndex index="0">FIELD:settings.detailauswahl:=:1</numIndex>
  4.     <numIndex index="1">FIELD:settings.detailauswahl:=:2</numIndex>
  5.   </OR>
  6. </displayCond>


und für eine Und-Abfrage (AND):

  1. <displayCond>
  2.   <AND>
  3.     <numIndex>FIELD:settings.detailauswahl:=:1</numIndex>
  4.     <numIndex>FIELD:settings.bildauswahl:=:2</numIndex>
  5.   </AND>
  6. </displayCond>

Der wichtige Unterschied zwischen AND und OR ist, dass bei einer OR-Abfrage jeder Überprüfung ein Index hinzugefügt werden muss. 

Konfiguration: Radiobuttons

Wenn der Type einer Checkbox von "check" zu "radio" geändert wird, können Radiobuttons verwendet werden:

  1. <config>
  2.   <type>radio</type>
  3.   <items type="array">
  4.     <numIndex index="0" type="array">
  5.       <numIndex index="0">Auswahl0</numIndex>
  6.       <numIndex index="1">0</numIndex>
  7.     </numIndex>
  8.     <numIndex index="1" type="array">
  9.       <numIndex index="0">Auswahl1</numIndex>
  10.       <numIndex index="1">1</numIndex>
  11.     </numIndex>
  12.     <numIndex index="2" type="array">
  13.       <numIndex index="0">Auswahl2</numIndex>
  14.       <numIndex index="1">2</numIndex>
  15.     </numIndex>
  16.   </items>
  17. </config>

Wizard-Konfiguration: Tabelle

In den DCEs ist es leider nicht möglich eine Tabellenkonfiguration auszuwählen. Es ist aber möglich eine eigene Konfiguration für den Typo3 Standard Tabellen Wizard zu schreiben. Dazu benötigt man noch einen eigenen Tabellen ViewHelper, der die Daten entsprechend umsetzt. 

  1. <config>
  2.   <type>text</type>
  3.   <size>500</size>
  4.   <row>500</row>
  5.   <col>20</col>
  6.   <wizards>
  7.     <_PADDING>2</_PADDING>
  8.     <link>
  9.       <type>script</type>
  10.       <title>LLL:EXT:cms/locallang_ttc.xlf:bodytext.W.table</title>
  11.       <icon>content-table</icon>
  12.       <module>
  13.         <name>wizard_table</name>
  14.         <urlParameters>
  15.           <mode>wizard</mode>
  16.         </urlParameters>
  17.       </module>
  18.       <params>
  19.         <numNewRows>1</numNewRows>
  20.       </params>
  21.     </link>
  22.   </wizards>
  23. </config>

 

Und führt zu dieser Ausgabe im Backend:

Ein Klick auf den Button öffnet den Wizard:

Wenn Daten in den Wizard eingegeben und gespeichert werden, dann sieht dies so aus:

FLUID-Programmierung

Die Templates der DCEs werden mit Fluid-Programmierung festgelegt. Das bedeutet, sie alleine bestimmen, wie die Backend-Eingaben im Frontend ausgegeben werden.

Fluid ist eine "Template engine". Sie ist einfach zu verwenden und zu erweitern. Diese Art der Programmierung wird seit einiger Zeit in Typo3 selbst und auch in den neueren Extensionen verwendet. Daher kommt sie auch in der Extension DCE zum Einsatz.

Ein großer Vorteil von Fluid ist es, dass sich bequem Abfragen, Schleifen und Bedingungen mit HTML und CSS verbinden lassen. 

Template Datei

Das Template kann in einer externen Datei geschrieben. Auf diese Weise lassen sich Templates schnell in verschiedenen Typo3 Systemen verwenden und einfacher in verschiedene Unter-Templates aufteilen.

Inline Template

Die zweite Möglichkeit ist, das Template direkt "Inline" auf diesem Reiter zu definieren. Dies ist sinnvoller, wenn ein einfaches Template verwendet wird, welches sich nicht in einem anderen DCE wiederholt.

Standardmäßig ist diese Möglichkeit ausgewählt. Die Standardvorgabe eines Inline-Templates sieht folgendermaßen aus:

  1. {namespace dce=ArminVieweg\Dce\ViewHelpers}
  2. <f:layout name="Default" />
  3.  
  4. <f:section name="main"> 
  5.   Your template goes here...
  6. </f:section> 

Der "namespace" beschreibt den Ort, an dem sich die entsprechenden Dateien in der Ordner-Struktur befinden. 

Mit <f:layout> wird das umschließende Layout bestimmt. Im Standardfall ist dies bei den DCEs festgesetzt als "Default" und fügt damit ein umschließendes <div> ein:

  1. <div class="tx-dce-pi1"> 
  2.   Your template goes here...
  3. </div>

Soll das umschließende <div> entfernt werden, muss das "Default" durch ein "None" ersetzt werden. Dann wird ein leeres Layout verwendet.

  

Innerhalb der Section "main" wird das eigentliche Template geschrieben. Dort lassen sich die vorher definierten Variablen einfügen.

Über Die Schaltfläche "Template-Inhalt" lassen sich Variablen und einige "ViewHelper" direkt auswählen. Ein ViewHelper ist ein vordefiniertes Stück Code, das dabei hilft die eingegebenen Inhalte in der gewünschten Form umzusetzen.

Verfügbare Variablen

Wird nun eine der Variablen ausgewählt, wird sie folgendermaßen eingefügt:

  1. <f:section name="main">
  2.   {field.text}
  3. </f:section>

Nun wird einfach die im Backend in das Eingabefeld gemachte Eingabe, bei Test als Klartext, bei Mehrfacheingabe als Array oder sonstiges, ausgegeben. Weitere Spezifikationen siehe nächste Kapitel.

Verfügbare Basis-Variablen

Meist verwendete View-Helper

Text rendern

Texte können ganz normal mit <p> eingefügt werden. Dies gilt jedoch nur, wenn in den Eingabefeldern, egal ob RTE oder normales Feld, reiner Fließtext eingegeben wird. Wenn dort auch HTML-Tags verwendet werden, der Text aber nur als

  1. <f:section name="main">
  2.   {field.text}
  3. </f:section>

eingebunden wird, dann werden die Tags auch als Klartext ausgegeben. Man erhält dann zum Beispiel mit der Eingabe: 

Die Ausgabe:

  1. <ul><li>Text ... </li><li>Text ... </li><li>Text ...</li></ul>

Um dies zu verhindern muss der Text mit dem "f.format.html-ViewHelper" gerendert werden:

  1. <f:section name="main">
  2.   <f:format.html>{field.text}</f:format.html>
  3. </f:section>

Dann wird der Text auch als richtige Liste ausgegeben.

Bilder einfügen

Ein Bild kann auf unterschiedliche Arten eingefügt werden. Erst einmal ist wichtig, mit welcher Methode das Bild ausgewählt werden soll.

Dazu gibt es TYPE:group "File upload" und TYPE:fal "File Abstraction Layer". Wobei sich letzteres in Sektion und nicht Sektion unterteilt. 

TYPE:group „File upload“

Wenn das Bild mit Hilfe von "File upload" eingebunden wurde, kann es direkt mit dem "f:image-ViewHelper" eingefügt werden. Dazu muss der "uploadfolder" angegeben werden, wenn er in der Konfiguration festgelegt wurde. Gibt es dort keinen, dann reicht die Angabe der Variablen. Die Standardangabe wäre also:

  1. <f:image src="uploads/pics/{field.image}" alt="" />

Das Ergebnis ist ein normaler <img> HTML-Tag.

Wird der "File Abstraction Layer" verwendet, so muss bis zur Version 1.4.0 das Bild mit Hilfe des "dce:fal-ViewHelper" eingebunden werden:

  1. <f:for each="{dce:fal(field:'image', contentObject:contentObject)}" as="fileReference">
  2.   <f:image src="{fileReference.uid}" treatIdAsReference="1" />
  3. </f:for>

Das Ergebnis ist auch hier ein normaler <img>-Tag. Die "fileReference" lässt sich durch eine beliebige Bezeichnung ersetzen. Dies ist zum Beispiel nötig, wenn mehrere Dateien ineinander verschachtelt werden müssen.

Das FAL-Element kann auch als Hintergrundbild eingebaut werden:

  1. <f:for each="{dce:fal(field:'image', contentObject:contentObject)}" as="fileReference">
  2.   <div style="background-image: url('{f:uri.image(src:'{fileReference.uid}', treatIdAsReference:'1')}');"></div>
  3. </f:for>

 

Ab der Version 1.4.0 ist es möglich FAL-Bilder auch direkt, ohne den "dce:fal-ViewHelper". einzubinden. Dazu wird dann verwendet:

  1. <f:for each="{field.image}" as="fileReference" />
  2.   <f:image image="{fileReference}" />
  3. </f:for>

Dazu müssen zur Konfiguration zwei Zeilen hinzugefügt werden, diese sind aber in der neuen Standard-Konfiguration direkt vorhanden:

  1. <dce_load_schema>1</dce_load_schema>
  2. <dce_get_fal_objects>1</dce_get_fal_objects> 

 

Wird das Bild als FAL eingebaut, so kann ein Titel, ein Alt-Text, ein Link und eine Beschreibung angegeben werden.

Wenn man diese im Frontend ausgeben möchte, muss dafür im DCE-Template folgender Code verwendet werden:

  1. <f:foreach="{field.image}"as="fileReference">
  2.   <f:link.page pageUid="{fileReference.link}">
  3.     <f:imageimage="{fileReference.uid}"treatIdAsReference="1" title="{fileReference.title}" alt="{fileReference.alternative}"/>
  4.     <p>{fileReference.description}</p>
  5.   </f:link.page>
  6. </f:for>

TYPE:fal "File Abstraction Layer (section use only)"

Wird ein FAL-Element in einer Sektion verwendet, dann wird das Bild nicht als "image", sondern als "file" eingebunden:

  1. <f:for each="{field.bilder}" as="bilder">
  2.   <f:for each="{bilder.image -> dce:explode()}" as="imageUid">
  3.     <img src="<f:uri.image src="file:{imageUid}" />">
  4.   </f:for>
  5. </f:for>

 

Das geht natürlich auch als Hintergrundbild:

  1. <f:for each="{field.bilder}" as="bilder">
  2.   <f:for each="{bilder.image -> dce:explode()}" as="imageUid">
  3.     <div style="background-image:url('<f:uri.image src="file:{imageUid}" />')">
  4.   </f:for>
  5. </f:for>

Responsive Bilder

Bilder sind durch FAL auch leicht responsiv verwendbar. Es wird einfach das Bild im größten verwendeten Format hochgeladen und die View-Helper sorgen für die verschiedenen Skalierungen des Bildes:

  1. <f:for each="{field.image}" as="fileReference">
  2.   <picture>
  3.     <source srcset="<f:uri.image src='{fileReference.uid}' treatIdAsReference='1' width='400' />" media="(max-width: 400px)">
  4.     <source srcset="<f:uri.image src='{fileReference.uid}' treatIdAsReference='1' width='700' />" media="(max-width: 700px)">
  5.     <source srcset="<f:uri.image src='{fileReference.uid}' treatIdAsReference='1' width='1000' />" media="(max-width: 1000px)">
  6.     <img src="<f:uri.image src='{fileReference.uid}' treatIdAsReference='1' width='1000' />" />
  7.   </picture>
  8. </f:for>

Das ergibt dann im HTML-Code:

  1. <picture>
  2.   <source srcset="_processed_/csm_image_d299f7ab95.jpgmedia="(max-width: 400px)">
  3.   <source srcset="_processed_/csm_image_390vnj3099.jpgmedia="(max-width: 700px)">
  4.   <source srcset="_processed_/csm_image_8d7e1e819e.jpgmedia="(max-width: 1000px)">
  5.   <img src="image.jpg" />
  6. </picture>

Wichtig ist, das hinter "source" "srcset" stehen muss, während hinter "img" nur "src" stehen darf. Letzteres sorgt dafür, dass der Internet Explorer überhaupt etwas anzeigen kann und ersteres wird von allen anderen Browsern für die responsiven Bilder verwendet.

 

In Typo3 Version 8.x.x können über den Image Editor eigene Crop-Varianten festgelegt werden. Auch auf diese kann man über DCEs zugreifen. Im TSconfig wird zum Beispiel definiert:

  1. TCEFORM.sys_file_reference.crop.config.cropVariants {
  2.   default {
  3.     title = Desktop
  4.     selectedRatio = 5:3
  5.     allowedAspectRatios {
  6.       NaN {
  7.         title = Free
  8.         value = 0.0
  9.       }
  10.       5:3 {
  11.         title = Normal
  12.         value = 1.666666
  13.       }
  14.       1:1 {
  15.         title = Quadratisch
  16.         value = 1
  17.       }
  18.     }
  19.   }
  20. }

Mit "default" wird der Name bestimmt, mit dem die jeweilige Version aufgerufen wird. Hier können zum Beispiel mehrere Varianten generiert werden:

Dann kan man in FLUID auf die cropVarianten zugreifen durch folgenden Code:

  1. <f:for each="{field.images}" as="image">
  2.   <picture>
  3.     <sourcesrcset="<f:uri.image src='{image.uid}' treatIdAsReference='1' cropVariant='mobile' />"media="(max-width: 420px)">
  4.     <sourcesrcset="<f:uri.image src='{image.uid}' treatIdAsReference='1' cropVariant='tablet' />"media="(max-width: 768px)">
  5.     <sourcesrcset="<f:uri.image src='{image.uid}' treatIdAsReference='1' cropVariant='desktop' />"media="(max-width: 1024px)">
  6.     <sourcesrcset="<f:uri.image src='{image.uid}' treatIdAsReference='1' cropVariant='desktop' />"media="(min-width: 1200px)">
  7.     <f:imagesrc="<f:uri.image src='{image.uid}' treatIdAsReference='1' cropVariant='desktop' />"alt="{image.alternative}"/>
  8.   </picture>
  9. </f:for>

 

Eine weitere Möglichkeit ist es, Bilder mit Hilfe von Typoscript responsiv einzubinden. Dazu wird zunächst in Typoscript definiert, wie die responsiven Bilder aussehen sollen:

  1. lib{
  2.   responsiveImage = IMAGE
  3.   responsiveImage {
  4.     file {
  5.       import.current = 1
  6.       treatIdAsReference = 1
  7.     }
  8.     layoutKey = picture
  9.     layout {
  10.       picture {
  11.         element = <picture>###SOURCECOLLECTION###<img src="###SRC###" /></picture>
  12.         source = <source srcset="###SRC###" media="###MEDIAQUERY###" />
  13.       }
  14.     }
  15.     sourceCollection {
  16.       small {
  17.         width = 400
  18.         mediaQuery = (max-width: 420px)
  19.       }
  20.       medium {
  21.          width = 700
  22.          mediaQuery = (max-width: 768px)
  23.       }
  24.       big {
  25.         width = 1000
  26.         mediaQuery = (max-width: 1024px)
  27.       }
  28.     }
  29.   }
  30. }

 

Dann kann ein FAL-Bild einfach als cObject eingebunden werden:

  1. <f:for each="{field.image}" as="image">
  2.   <f:cObject typoscriptObjectPath="lib.responsiveImage" data="{image.uid}"></f:cObject>
  3. </f:for>

Verlinkungen

Bei Verlinkungen wird zwischen internen und externen Links unterschieden. Beide Verlinkungen können auf unterschiedliche Weisen verwendet werden. Eine „unschöne“ aber funktionierende Lösung ist ein einfaches Eingabefeld, in das die Verlinkung geschrieben wird und dann mit einem <a>-Tag aufgerufen wird:

  1. <a href="{field.link}">Page</a>

Dies funktioniert immer mit externen und internen Links, hat aber den Nachteil, das absolute Verlinkungen angegeben werden müssen. 

Es gibt vier Konfigurationen mit denen sich Verlinkungen einbauen lassen:

Die erste Möglichkeit eignet sich für interne, externe und Anker Verlinkungen, sowie die Auswahl von Dateien und E-Mail-Verlinkungen.
Wenn man eine Unterseite und einen Datensatz mit Hilfe von TYPE:input "Typolink" auswählt, dann wird im Frontend die Seiten-Id und die Datensatz-Id zurückgegeben. Es ist also sowohl möglich den "f:link.page-ViewHelper":

  1. <f:link.page pageUid="{field.link}">Page</f:link.page>

oder der "dce:typolink-ViewHelper" zu verwenden:

  1. <dce:typolink parameter="{field.link}">Page</dce:typolink>

Wenn eine externe URL ausgewählt worden ist, dann bietet es sich an den "f:link.external-ViewHelper" zu verwenden:

  1. <f:link.external uri="{field.link}" target="_blank">Website</f:link.external>

Bei der Auswahl einer E-Mail-Adresse muss jedoch einer der beiden ViewHelper für interne Verlinkungen gewählt werden. Diese fügen dann vor der E-Mail-Adresse direkt ein "mailto:" ein.

Externe Verlinkungen

Bei einer externen Verlinkung ist normalerweise sowieso ein absoluter Link gegeben. Daher bietet sich ein einfaches Eingabefeld an, das dann mit dem "f:link.external-ViewHelper" verwendet wird:

  1. <f:link.external uri="{field.link}" target="_blank">Website</f:link.external>

Interne Verlinkungen

Mit folgenden drei Möglichkeiten, können ausschließlich interne Verknüpfungen zu Unterseiten erzeugt werden:

Die Rückgabe ist dabei jeweils die Seiten-Id. Um dieses auszuwerten, wird entweder der "f:link.page-ViewHelper":

  1. <f:link.page pageUid="{field.link}">Page</f:link.page>

oder der "dce:typolink-ViewHelper" verwendet:

  1. <dce:typolink parameter="{field.link}">Page</dce:typolink>

Ankerpunkte

Wenn ein Punkt auf derselben Seite, also ein Ankerpunkt erreicht werden soll, so kann dies einfach durch die Seiten-Id umgesetzt werden:

  1. <f:link.page pageUid="{contentObject.pid}#{field.link}">Page</f:link.page>

oder:

  1. <dce.typolink parameter="{contentObject.pid}#{field.link}">Page</typolink>

Tabelle

Tabellen-Konfiguration im FLUID verwenden zu können, muss man einen neuen ViewHelper definieren.

Dieser muss in den Ordner "EXT:dce/Classes/ViewHelpers" unter dem Namen "TabelleViewHelper.php" gespeichert werden und kann zum Beispiel so aussehen wie der von hier:

  1. <?php
  2. namespace ArminVieweg\Dce\ViewHelpers;
  3. use TYPO3\CMS\Core\Utility\GeneralUtility;
  4. class TabelleViewHelper extends \TYPO3\CMS\Fluid\Core\ViewHelper\AbstractViewHelper {
  5.    /**
  6.    * @var \TYPO3\CMS\CssStyledContent\Controller\CssStyledContentController
  7.    * @inject
  8.    */
  9.    protected $cscController;
  10.     /**
  11.     * @var \TYPO3\CMS\Extbase\Configuration\ConfigurationManager
  12.     * @inject
  13.     */
  14.    protected $configurationManager;
  15.     /**
  16.     * Arguments Initialization
  17.     */
  18.     public function initializeArguments() {
  19.       $this->registerArgument('table', 'string', 'Die Tabellen-Daten, Delimiter ist das Pipe-Symbol', falsenull);
  20.       $this->registerArgument('layout', 'string', 'Die Zahl, die an der Klasse contenttable-XX erscheint', falsenull);
  21.    }
  22.      /**
  23.      * Rendert die Tabelle mit csc_styled_content
  24.      */
  25.      public function render() {
  26.        if (!$this->arguments['table']) {
  27.          $this->arguments['table'] = html_entity_decode($this->renderChildren());
  28.       }
  29.        $this->cscController->cObj = $this->configurationManager->getContentObject();
  30.       $this->cscController->cObj->data = $this->arguments;
  31.       return $this->cscController->render_table( null, array('field'=>'table') );
  32.     }
  33. }
  34. ?>

Dann wird die Tabelle ganz normal als Tabelle angezeigt.

 

Wenn das Einfügen der Tabelle direkt über die Variablen funktionieren soll, muss unter "EXT:/dce/Resources/Public/CodeSnippets/DceViewHelpers" eine Datei namens "tabelle.html" vorhanden sein, mit folgendem Inhalt:

  1. <dce:tabelle>{tabelle}</dce:tabelle>

IF-Abfragen

Eine IF-Abfrage besteht aus einer "condition", der Bedingung, einem "then"-Teil und einem "else"-Teil. Zunächst wird abgefragt, welche Bedingung erfüllt sein muss, um entweder bei Erfüllung den "then"-Teil, oder bei nicht Erfüllung den "else"-Teil auszuführen. Wobei der "else"-Teil auch weggelassen werden kann. IF-Abfragen können beliebig oft verschachtelt werden.

  1. <f:if condition="">
  2.   <f:then>
  3.  
  4.   </f:then>
  5.   <f:else>
  6.  
  7.   </f:else>
  8. </f:if>

Mit einer IF-Abfrage kann gesteuert werden, welcher HTML-Code im Frontend ausgegeben wird. Zunächst kann überprüft werden, ob ein Inputfeld generell ausgefüllt worden ist. Und dann gibt es zwei Möglichkeiten, wie die Eingaben für IF-Abfragen aussehen können. Mit einer Checkbox kann zum Beispiel  "entweder - oder" abgefragt werden und mit einer manuellen Liste lassen sich die eingegebenen "conditions" abfragen.

Es kann abgefragt werden, ob das Feld "Text" ausgefüllt wurde:

  1. <f:if condition="{field.text}">

Es kann eine "OR" (||) und eine "AND" (&&) Abfrage gestellt werden:

  1. <f:if condition="{field.header} || {field.text}">

Es kann ein konkreter Wert überprüft werden (auch <, <=, >, <= und !=):

  1. <f:if condition="{field.text} == 1">

Vermeidung von leeren HTML-Tags

Mit Hilfe einer IF-Abfrage kann dann verhindert werden, das leere HTML-Elemente eingebaut werden. Wenn zum Beispiel einbaut wird:

  1. <h1>{field.header}</h1>

ergibt dies einen leeren HTML <h1>-Tag, wenn im Backend in das Feld für "header" nichts eingetragen wurde. Wird stattdessen geschrieben

  1. <f:if condition="{field.header}">
  2.   <f:then>
  3.     <h1>{field.header}</h1>
  4.   </f:then>
  5. </f:if>

dann wird kein <h1>-Tag eingefügt, wenn das Feld für "header" nicht ausgefüllt wurde.

Manuelle Liste

Bei einer manuellen Liste können alle vorgegebenen Auswahl-Möglichkeiten überprüft werden. Zum Beispiel, die Auswahl der Header-Ebene. In der manuellen Liste werden die Auswahlmöglichkeiten "H1", "H2" und "H3" gegeben. Mit der IF-Abfrage kann man dann den entsprechenden Code ausgeben:

  1. <f:if condition="{field.headerebene}==1">
  2.   <f:then>
  3.     <h1>{field.headerebene}</h1>
  4.   </f:then>
  5. </f:if>
  6. <f:if condition="{field.headerebene}==2">
  7.   <f:then>
  8.     <h2>{field.headerebene}</h2>
  9.   </f:then>
  10. </f:if>
  11. <f:if condition="{field.headerebene}==3">
  12.   <f:then>
  13.     <h3>{field.headerebene}</h3>
  14.   </f:then>
  15. </f:if>

Verwendet man die Konfiguration, wie oben geschrieben, dann kann man auch verkürzt verwenden:

  1. <f:if condition="{field.header}">
  2.   <f:then>
  3.    <h{field.headerebene}>{field.header}</h{field.headerebene}>
  4.   </f:then>
  5. </f:if>

Checkbox

Mit einer Checkbox kann zum Beispiel ausgewählt werden, ob ein Text fett sein soll oder nicht. Von der IF-Abfrage wird hier nun der Zustand geprüft. Wobei eine ausgefüllte Box ein "true" zurück gibt, und somit den "then"-Teil auslöst und eine nicht ausgefüllte "false" und damit den "else"-Teil. Zum Beispiel, wenn abgefragt wird, ob der Text fett sein soll, oder nicht:

  1. <f:if condition="{field.textfett}">
  2.   <f:then>
  3.     <b>{field.text}</b>
  4.   </f:then>
  5.   <f:else>
  6.     {field.text}
  7.   </f:else>
  8. </f:if>

FOR-Schleifen

Wenn eine Sektion verwendet wird, dann müssen die Eingaben aus dieser mit einer FOR-Schleife ausgegeben werden:

  1. <f:for each="{field.testsektion}" as="test">
  2.   <h1>{test.header}</h1>
  3. </f:for>

Sollen nicht alle Elemente aus seiner Sektion verwendet werden, so lässt sich das zum Beispiel über einen Iterator steuern:

  1. <f:for each="{field.testsektion}" as="test" iteration="iterator">
  2.   <f:if condition="{iterator.index} <= 5">
  3.     <f:then>
  4.       <h1>{test.header}</h1>
  5.     </f:then>
  6.   </f:if>
  7. </f:for>

Das bedeutet, dass nur die ersten fünf Iterationen der Sektion ausgegeben werden. Achtung, der Iterator beginnt bei 0 zu zählen! Mit folgendem Code lässt sich nur die erste Iteration ausgeben:

  1. <f:for each="{field.testsektion}" as="test" iteration="iterator">
  2.   <f:if condition="{iterator.isFirst}">
  3.     </f:then>
  4.       <h1>{test.header}</h1>
  5.     </f:then>
  6.   </f:if>
  7. </f:for>

Analaog kann mit {iterator.isLast} das letzte Element gewählt werden.

Wenn mit "Link Pages and get pages as associative array" eine Dateisammlung eingefügt werden soll, wird auch dafür eine FOR-Schleife verwendet:

  1. <f:for each="{field.testgroup}" as="collection">
  2.   <f:for each="{collection.items}" as="item">
  3.     <f:image src="{item.uid}" treatIdAsReference="{f:if(condition:'{item.originalFile}',then: '1', else: '0')}" />
  4.   </f:for>
  5. </f:for>

Mit Hilfe von FOR-Schleifen ist es auch möglich einer Reihe von <div>-Elementen eine fortlaufende ID zuzuweisen:

  1. <f:for each="{field.items}" as="item" iteration="iterator">
  2.   <div id="unique-name-{iterator.index}"></div>
  3. </f:for>

Soll die ID nicht nur auf dieser Seite, sondern allgemein einzigartig sein, so ist dies über die UID der Seite möglich. Diese wird mit {contentObject.pid} ausgelesen:

  1. <f:for each="{field.items}" as="item" iteration="iterator">
  2.   <div id="unique-name-{contentObject.pid}-{iterator.index}"></div>
  3. </f:for>

Tipps und Beispiele

Tabs

Für eine bessere Übersichtlichkeit und einfachere Nutzung durch den Redakteur lassen sich die Tabs verwenden. Zum Beispiel kann man ein Tab für Text erstellen, eines für Bilder und eines für Videos. Mit Hilfe von If-Abfragen kann überprüft werden, welche von den Feldern ausgefüllt worden sind und diese dann entsprechend anzeigen lassen.

Überschrift und Text

Eine Überschrift lässt sich am einfachsten mit einem einfachen "Input-Field" einfügen. Für den Text lässt sich besser ein "Inherit RTE from TSconfig" verwenden, da in einem Fließtext häufig vom Redakteur Einstellungen vorgenommen werden müssen, wie zum Beispiel Listen oder Verlinkungen. Im Backend sieht das so aus:

In einem Template muss nun definiert werden, wie das Ergebnis im Frontend aussehen soll. Dazu müssen die vergebenen Variablen eingesetzt werden. Die Überschrift kann einfach in einen <h2>-Tag gesetzt werden, während der Text von einem View-Helper umgeben werden muss, damit die im Backend vorgenommenen HTML-Programmierungen umgesetzt werden können, denn ansonsten würden die HTML-Codierungen direkt ausgegeben werden. Dann würde zum Beispiel, bei einem manuell gesetzten <br>, kein Zeilenumbruch gemacht, sondern der Text "<br>" ausgegeben.

  1. {namespace dce=ArminVieweg\Dce\ViewHelpers}
  2. <f:layout name="Default"/>
  3.  
  4. <f:section name="main">
  5.   <h2>{field.header}</h2>
  6.   <f:format.html>{field.text}</f:format.html>
  7. </f:section>

Wenn im Backend vom Redakteur keine HTML-Codierungen von Hand hinzugefügt werden, dann wird der gesamte eingefügte Text durch ein umschließendes <p></p> eingerahmt.

Video und Poster per FAL

Wenn zum Beispiel ein Video und ein entsprechendes Poster per FAL ausgewählt werden können, dann erfolgt die Ausgabe für das Frontend durch folgenden Code:

  1. <f:for each="{field.video}" as="video">
  2.   <f:for each="{field.poster}" as="poster">
  3.     <video poster="{f:uri.image(src:'{poster.uid}',treatIdAsReference:'1')}">
  4.       <source src="{f:uri.image(src:'{video.uid}',treatIdAsReference:'1')}"/>
  5.     </video>
  6.   </f:for>
  7. </f:for>

Mehrsprachigkeit

Wenn man zum Beispiel einen Button einbauen möchte, der immer den gleichen Text enthalten soll, so kann man diesen ja einfach fest kodieren im DCE. Hat man aber mehrere Sprachen auf der Website, so geht das nicht mehr ganz so einfach. Aber mit Hilfe einer "lang.xml" Datei und einem Verweis auf diese, ist auch das Problem leicht zu lösen. Man erstellt also eine lang.xml mit folgendem Inhalt:

  1. <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
  2. <T3locallang>
  3.   <meta type="array">
  4.     <typ>module</type>
  5.     <description>Language labels for the DCEs in backend</description>
  6.   </meta>
  7.   <data type="array">
  8.     <languageKey index="de" type="array">
  9.       <label index="buttontext">Weiter</label>
  10.     </languageKey>
  11.     <languageKey index="default" type="array">
  12.       <label index="buttontext">Next</label>
  13.     </languageKey>
  14.   </data>
  15. </T3locallang>

Und schreibt dann ins FLUID-Template:

  1. <a href="#">
  2.   <f:translate key="LLL:fileadmin/lang/dce.xml:buttontext">
  3. </a>

Auf diese Weise können mehrere Sprachen definiert werden. Wichtig ist nur zu wissen, das Englisch, also "en" immer "default" ist. Auch wenn die eigentliche Default-Sprache Deutsch ist.

Den Titel oder Navigationstitel einer Seite auslesen

Mit Hilfe von FLUID kann man in einem DCE auch einfach den Seitentitel einer Website auslesen und direkt ausgeben.

  1. <f:ifcondition="{page.navtitle}">
  2.   <f:then>
  3.     <h1>{page.navtitle}</h1>
  4.   </f:then>
  5.   <f:else>
  6.     <h1>{page.title}</h1>
  7.   </f:else>
  8. </f:if>

PDF einbinden

Ein PDF kann mit Hilfe von FAL-Objekten genauso wie ein Bild oder Video eingefügt werden. Wenn man aber hier den selben Code wie bei einem Bild verwendet, wird lediglich ein Bild der PDF angezeigt. 

Will man einen Button "Download" erzeugen, bei dem sich die PDF-Datei öffnet, so muss dies mit "publicUrl" umgesetzt werden:

  1. <f:for each="{field.pdf}" as="pdf">
  2.   <a href="{pdf.publicUrl}" target="_blank">Download</a>
  3. </f:for>

Gleichzeitig kann man auch ein Bild der PDF anzeigen, bei dem sich dann auch der Download auf Klick öffnet:

  1. <f:for each="{field.pdf}" as="pdf">
  2.   <a href="{pdf.publicUrl}" target="_blank">
  3.     <f:image image="{pdf}"/>
  4.   </a>
  5. </f:for>

Andere DCEs anzeigen

Wenn auf beliebige andere DCEs oder generelle tt_content Elemente zugegriffen werden soll, kann einfach mit der Standardkonfiguration von "Link Pages and get pages as associative array" eine Auswahl getroffen werden. Dazu muss nur der <foreign_table>pages</foreign_table> durch <foreign_table>tt_content</foreign_table> ersetzt werden. Es öffnet sich der bekannte Typo3 Wizard. Auf jeder Seite kann jedes Element gewählt werden. 

Aber mit einer Veränderung der "Automatical list of items" Konfiguration kann zum Beispiel bestimmt werden, von welcher Seite nur Elemente gewählt werden dürfen. Außerdem lässt sich mit Hilfe des <renderType> eine schönere Ansicht erzeugen. Die Konfiguration lautet:

  1. <config>
  2.   <type>select</type>
  3.   <foreign_table>tt_content</foreign_table>
  4.   <renderType>selectMultipleSideBySide</renderType>
  5.   <foreign_table_where>AND tt_content.pid = 27</foreign_table_where>
  6.   <enableMultiSelectFilterTextfield>1</enableMultiSelectFilterTextfield>
  7.   <size>10</size>
  8.   <minitems>0</minitems>
  9.   <maxitems>99</maxitems>
  10.   <dce_load_schema>1</dce_load_schema>
  11. </config>

Wichtig ist die Zeile <dce_load_schema>1</dce_load_schema>. Ohne diese kann lediglich die Element-UID ausgegeben werden. Es erfolgt kein Zugriff auf die einzelnenen Elemente in der DCE-Instanz.

Im Backend können dann alle, auf der Seite mit UID 27, Elemente verwendet werden:

Damit sich die DCE-Instanzen besser auseinander halten lassen, kann man im Backend-Template über die "header-section" ein zweites Feld anzeigen lassen:

  1. <f:sectionname="header">
  2.   <h1>{dce.title}</h1>
  3.   <h2>{field.id}</h2>
  4. </f:section>

Mit Hilfe von <foreign_table_where>AND tt_content.pid = ###CURRENT_PID###</foreign_table_where> kann die Auswahl auch auf Elemente auf derselben Seite beschränkt werden. 

Will man die Auswahl nur auf DCE Instanzen beschränken, in denen das gewünschte Feld auch ausgefüllt ist, so kann man das entprechende Feld auf eine TCA-Spalte mappen und dann mit Hilfe dieser nur die ausgefüllten DCEs anzeigen lassen. Hier werden alle Felder angezeigt, in denen das auf "header" gemappte Feld nicht leer ist:

  1.     <foreign_table_where>AND tt_content.header != ""</foreign_table_where>

 

Das vollständige ausgewählte DCE lässt sich im Template dann mit einer for-Schleife anzeigen:

  1. <f:for each="{field.auswahl}" as="otherDce">
  2.   {otherDce.render -> f:format.raw()}
  3. </f:for>

 

Aber es ist auch möglich, nur eine bestimmte Variable aus dem anderen DCE anzeigen. Das ist besonders praktisch, wenn man zum Beispiel Ankerpunkte auf einer Seite angelegt hat und in den dazu gehörenden Sprungmarken nicht die ID des Ankers wieder neu schreiben möchte (besonders wichtig bei Anker-Seo):

  1. <f:for each="{field.auswahl}" as="otherDce">
  2.   {otherDce.header}
  3. </f:for>