Fluid wurde ursprünglich als Template-Sprache für FLOW und Extbase entwickelt, ist aber auch zum Rendern der Frontend-Ausgabe geeignet. In Fluid kann direkt auf zur Verfügung stehende Variablen und Objekte zugegriffen werden. Zusätzlich stellen sogenannte ViewHelper verschiedene Funktionen zur Verfügung, von Datumsformatierungen bis zu Schleifen und Bedingungen.
Bei Fluid Templates wird die HTML-Vorlage in mehrere Teile zerlegt:
lib.mainMenu = HMENU lib.mainMenu { [...] } page = PAGE page { # Einfügen von CSS, Javascript, Metadaten etc. wie üblich 10 = FLUIDTEMPLATE 10 { file = EXT:templates/Resources/Private/Templates/2-columns.html layoutRootPath = EXT:templates/Resources/Private/Layouts/ partialRootPath = EXT:templates/Resources/Private/Partials/ variables { content < styles.content.get contentRight < styles.content.getRight header = IMAGE header { [...] } mainMenu < lib.mainMenu footer = TEXT footer { [...] } } } }
Beispiel für ein zweispaltiges Template
EXT:templates/Resources/Private/Templates/2columns.html
<!-- Einfügen des Layouts (Dateiname ohne Endung) --> <f:layout name="DefaultLayout" /> <f:section name="body"> <div id="main"> <div id="main-menu"> <f:format.raw>{mainMenu}</f:format.raw> </div> <div id="content"> <f:format.raw>{content}</f:format.raw> </div> <div id="right"> <f:format.raw>{contentRight}</f:format.raw> </div> </div> </f:section>
Beispiel für ein grundlegendes Layout
EXT:templates/Resources/Private/Layouts/DefaultLayout.html
<div id="wrapper"> <div id="header"> <f:format.raw>{header}</f:format.raw> </div> <!-- Einfügen des Templates (Name der Sektion) --> <f:render section="body" /> <div id="footer"> <f:format.raw>{footer}</f:format.raw> </div> </div>
Zu den HTML-Templates werden passende BackendLayouts angelegt, welche auf den Seiten im Backend eingebunden werden können. Im zweiten Teil des cObjects CASE
werden sie einander zugeordnet.
Im Key des cObjects CASE
wird ausgelesen, welches BackendLayout einer Seite zugewiesen wurde. Falls der aktuellen Seite kein BackendLayout zugewiesen wurde, soll das Template der darüber liegenden Seite genutzt werden. Falls bis zum root kein BackendLayout zu finden ist, wird der default-Wert genutzt.
page.10 = FLUIDTEMPLATE page.10 { file.cObject = CASE file.cObject { key { # -1 = aktuelle Seite | backend_etc = Feld in der Datenbank | slide = am rootPath entlang nach oben suchen data = levelfield:-1, backend_layout_next_level, slide override { data = TSFE:page|backend_layout } } # Nummerierung = ID des BackendLayouts! 1 = TEXT 1.value = EXT:templates/Resources/Private/Templates/Template-9-3.html 2 = TEXT 2.value = EXT:templates/Resources/Private/Templates/Template-6-6.html default = TEXT default.value = EXT:templates/Resources/Private/Templates/DefaultTemplate.html } }
In dieser Version wurde die Option pagelayout
eingeführt, um die Zuweisung von Templates mit Backend-Layouts zu vereinfachen:
page.10 = FLUIDTEMPLATE page.10 { file.stdWrap.cObject = CASE file.stdWrap.cObject { key.data = pagelayout # Nummerierung = ID des BackendLayouts! 1 = TEXT 1.value = EXT:templates/Resources/Private/Templates/Template-9-3.html 2 = TEXT 2.value = EXT:templates/Resources/Private/Templates/Template-6-6.html default = TEXT default.value = EXT:templates/Resources/Private/Templates/DefaultTemplate.html } }
mod.web_layout.BackendLayouts { 1 { title = Layout 3-1 (Standard) config { backend_layout { colCount = 3 rowCount = 1 rows { 1 { columns { 1 { name = Hauptspalte colspan = 2 colPos = 0 } 2 { name = rechte Spalte colPos = 2 } } } } } } icon = EXT:templates/Resources/Public/Images/BackendLayouts/BELayout_9-3.png } }
Zu beachten ist, dass BackendLayouts aus der TSconfig das Präfix pagets__
erhalten, um nicht mit manuell erstellten Layouts zu kollidieren.
page.10 = FLUIDTEMPLATE page.10 { file.stdWrap.cObject = CASE file.stdWrap.cObject { key.data = pagelayout // Nummerierung = ID des BackendLayouts! pagets__1 = TEXT pagets__1.value = EXT:templates/Resources/Private/Templates/Template-9-3.html pagets__2 = TEXT pagets__2.value = EXT:templates/Resources/Private/Templates/Template-6-6.html default = TEXT default.value = EXT:templates/Resources/Private/Templates/DefaultTemplate.html } }
TypoScript:
page.10 = FLUIDTEMPLATE page.10 { settings { mySetting = 0 } # etc. } [globalVar = TSFE:id=17] page.10.settings.mySetting = 1 [global]
Fluid-Template:
<f:if condition="settings.mySetting">do something</f:if>
Ab TYPO3 8.6 kann man Fluid verwenden, um benötigte Assets z.B. über eine Extension in der Seite zu ergänzen. Es sind praktische Alternativen zum TypoScript-Setup includeJSFooter
etc.
Fluid-Template:
<f:section name="HeaderAssets"> <!-- zusätzliche Inhalte im <head> --> </f:section> <f:section name="FooterAssets"> <!-- zusätzliche Inhalte vor </body> --> </f:section>
Quelle: TYPO3 Changelog #79413
<f:alias map="{footerClassList: 'c-site-footer c-site-footer--dark'}"> <f:render partial="Site/Footer" arguments="{_all}"/> </f:alias>
Quelle: Claus Fassing auf StackOverflow
Das folgende Snippet rendert einen Teil des Fluid-Templates nur, wenn die angegebene Inhaltsspalte auch Inhalt besitzt (der nicht deaktiviert ist). Praktisch z.B. für <aside>
Bereiche, die nicht auf jeder Unterseite enthalten sind.
Voraussetzung: das TypoScript-Objekt lib.dynamicContent muss vorhanden sein! Dies ist kein Teil des TYPO3-Kerns und muss selbst ergänzt werden.
Die Vorgehensweise mit cObject
und Variablenzuweisung hat zudem den Vorteil, dass nur eine Datenbankabfrage erfolgen muss.
{f:cObject(typoscriptObjectPath: 'lib.dynamicContent', data: {colPos: 0}) -> f:variable(name: 'content')} <f:if condition="{content}"> <aside class="optional-stuff"> // Render stuff </aside> </f:if>
Quelle: Claus Due auf StackOverflow
Eine f:if
-Condition kann problemlos innerhalb des name
-Arguments verwendet werden. Eine Condition um den f:layout
-Viewhelper herum würde aber nicht funktionieren.
<f:layout name="{f:if(condition: '{data.someData} == 123', then: 'SpecialLayout', else: 'Default')}" />
Quelle: Rudy Gnodde auf StackOverflow