Illustration: YAML-Konfiguration für benutzerdefinierte Formular-Templates

Eigene Templates im neuen EXT:form Framework zuweisen

TYPO3 v8 LTS bringt eine komplett überarbeitete Extension zur Erstellung beliebiger Formulare mit. Hier zeige ich, wie man angepasste Templates nur ausgewählten Formularen zuweist.

Einleitung

Die Konfiguration der neuen Form-Extension erfolgt komplett über YAML: Diese Auszeichnungs­sprache wurde mit Version 8 in TYPO3 eingeführt und ist dort auch für die Konfiguration des neuen Rich Text Editors ckeditor zuständig. Gerade für das Form Framework gibt es eine Vielzahl von Konfigurationen, da es bewusst flexibel gehalten wurde. Für einen TYPO3 Integrator ist dies im ersten Moment durchaus eine Umstellung. Im Backend-Modul von form gibt es jedoch einen sehr guten Editor, mit dem sich ein Formular leicht zusammenbauen lässt.

Ein großer Vorteil gegenüber den erprobten Formular-Extensions wie powermail ist, dass jedes erstellte Formular inklusive Felder, Validierungen und der Verarbeitung der übermittelten Daten (über die sogenannten Finisher) als YAML-Datei exportiert wird. Diese Dateien werden vom Form-Backend-Modul per Default im fileadmin gespeichert, können aber in Template-Extensions ausgelagert und versioniert werden. So ist es einfach möglich, Formulare als Gesamtpaket in andere TYPO3-Installationen zu übertragen.

Mittels YAML-Konfiguration kann man auch einrichten, dass man die in eine Extension ausgelagerten Formulare wieder im Backend-Modul bearbeiten kann. Diese Einstellung füge ich gleich ebenfalls hinzu.

Auf dieser englischsprachigen Seite wird das grundlegende Konzept der Form-Extension sehr ausführlich erklärt. Auf den Folgeseiten gibt es auch Referenzen der möglichen Konfigurationen und der API.

Das in der oben verlinkten offiziellen Dokumentation (Working Draft) aufgeführte Beispiel zum Anpassen von Template-Pfaden führt immer dazu, dass sämtliche Formulare der Website die geänderten Templates nutzen. Das ist aber nicht immer gewünscht. TypoScript-Conditions wären an dieser Stelle etwas umständlich. Es gibt aber auch einen eleganteren Weg, den ich im Folgenden zeige.

Wir benötigen mindestens zwei YAML-Konfigurationsdateien:

  • eine YAML-Datei, in der wir die Grundkonfiguration von form anpassen
  • eine YAML-Datei für jedes erstellte Formular

Dateistruktur

Als Speicherort nehme ich in diesem Tutorial eine Template-Extension, deren Ordnerstruktur auf TYPO3 Extbase-Extensions beruht:

  • ext_typoscript_setup.txt
    Die hier enthaltenen Konfigurationen werden direkt nach Installation der Extension verwendet.
  • Configuration/Yaml/CustomFormSetup.yaml
    Mit dieser Datei konfigurieren wir form nach unseren Vorstellungen.
  • Resources/Private/Forms/
    Hier werden die erstellen Formulare gespeichert.
  • Resources/Private/Frontend/Partials/
    Speicherort für angepasste Frontend Partials.
  • Resources/Private/Frontend/Templates/
    Speicherort für angepasste Frontend Templates.

Analog hierzu speichert man geänderte Templates für das Backend-Modul im Unterordner Resources/Private/Backend/Templates/. Beachtet bitte, dass ihr innerhalb dieser Ordner weiterhin die Ordnerstruktur und Dateibezeichnung von form beibehaltet: Das kleine Partial für den Pflichtfeld-Hinweis müsste im Ordner Resources/Private/Frontend/Partials/Field/Required.html gespeichert werden.

Für eine funktionierende Template-Extension muss natürlich eine Grundkonfiguration vorhanden sein (ext_emconf.php etc.). Alternativ kann jeder auf dem Webserver erreichbare Ordner für die Konfigurationsdateien und Templates verwendet werden, also auch ein Unterordner im fileadmin. Eine Template-Extension ist jedoch der saubere und bevorzugte Weg.

YAML-Konfiguration mit TypoScript einbinden

Zuerst einmal setzen wir über TypoScript den Pfad zu der YAML-Datei, mit der wir die Default-Konfigurationen überschreiben werden. Da die Nummern 10-30 bereits von EXT:form reserviert sind, starten wir einfach mit der Nummer 100, um unseren Pfad zum Array der Dateipfade hinzufügen.

Weil wir diese Datei auch für Konfigurationen im Backend verwenden werden, verlinken wir dies sowohl im Top Level Object plugin als auch unter module:

ext_typoscript_setup.txt

plugin.tx_form.settings.yamlConfigurations {
    100 = EXT:my_extension/Configuration/Yaml/CustomFormSetup.yaml
}

module.tx_form.settings.yamlConfigurations {
    100 = EXT:my_extension/Configuration/Yaml/CustomFormSetup.yaml
}

YAML-Konfiguration anlegen

Nun erstellen wir die oben verlinkte Konfigurationsdatei, in der wir für dieses Tutorial folgende Dinge einrichten:

  1. Wir legen mit allowedExtensionPaths fest, wo unsere erstellten Formulare gespeichert werden
  2. Mit allowSaveToExtensionPaths und allowDeleteFromExtensionPaths können Formulare im Backend-Modul gespeichert und auch gelöscht werden. Überlegt euch ob ihr ggf. darauf verzichtet, falls Redakteure Zugriff auf das Modul erhalten sollen.
  3. Wir erstellen einen neuen sogenannten prototype, den ich hier ganz plump mycontactform genannt habe. Der Name ist frei wählbar. Wichtig ist, dass wir mit dem Operator __inheritances noch eine Grundkonfiguration vom prototype standard kopieren. Dies funktioniert ähnlich wie der < Operator in TypoScript. Anschließend können wir die Pfade unserer Templates und Partials benennen.

CustomFormSetup.yaml

TYPO3:
  CMS:
    Form:
      persistenceManager:
        allowedExtensionPaths:
          10: EXT:my_extension/Resources/Private/Forms/
        allowSaveToExtensionPaths: true
        allowDeleteFromExtensionPaths: true

      prototypes:
        mycontactform:
          __inheritances:
            10: 'TYPO3.CMS.Form.prototypes.standard'
          formElementsDefinition:
            Form:
              renderingOptions:
                templateRootPaths:
                  100: 'EXT:my_extension/Resources/Private/Frontend/Templates/'
                partialRootPaths:
                  100: 'EXT:my_extension/Resources/Private/Frontend/Partials/'
                layoutRootPaths:
                  100: 'EXT:my_extension/Resources/Private/Frontend/Layouts/'

Ein Beispiel-Formular anlegen

Dieses Formular wird als Beispiel von form mitgebracht und kann im Backend-Modul geladen werden. Ich habe lediglich den prototypeName von standard auf unseren neuen prototype mycontactform geändert.

BasicContactForm.yaml

identifier: BasicContactForm
label: 'Basic contact form'
type: Form
prototypeName: mycontactform
finishers:
  -
    options:
      subject: 'Your message: {subject}'
      recipientAddress: your.company@example.com
      recipientName: 'Your Company name'
      senderAddress: '{email}'
      senderName: '{name}'
      replyToAddress: ''
      carbonCopyAddress: ''
      blindCarbonCopyAddress: ''
      format: html
      attachUploads: 'true'
      translation:
        language: ''
    identifier: EmailToReceiver
renderables:
  -
    identifier: page-1
    label: 'Contact Form'
    type: Page
    renderables:
      -
        defaultValue: ''
        identifier: name
        label: Name
        type: Text
        properties:
          fluidAdditionalAttributes:
            placeholder: Name
        validators:
          -
            identifier: NotEmpty
      -
        defaultValue: ''
        identifier: subject
        label: Subject
        type: Text
        properties:
          fluidAdditionalAttributes:
            placeholder: Subject
        validators:
          -
            identifier: NotEmpty
      -
        defaultValue: ''
        identifier: email
        label: Email
        type: Text
        properties:
          fluidAdditionalAttributes:
            placeholder: 'Email address'
        validators:
          -
            identifier: NotEmpty
          -
            identifier: EmailAddress
      -
        defaultValue: ''
        identifier: message
        label: Message
        type: Textarea
        properties:
          fluidAdditionalAttributes:
            placeholder: ''
        validators:
          -
            identifier: NotEmpty
  -
    identifier: summarypage
    label: 'Summary page'
    type: SummaryPage

Fazit

Das tolle ist, dass auf diese Weise jedes Formular ein individuelles Template erhalten kann, selbst wenn mehrere Formulare auf einer Seite existieren.

Nur für CSS-Klassen braucht man übrigens keine eigenen Templates – für diesen Zweck gibt es bereits verschiedene YAML-Konfigurationen! Die Default-Klassen stammen vom Bootstrap-Framework. Ein Beispiel:

TYPO3:
  CMS:
    Form:
      prototypes:
        standard:
          formElementsDefinition:
            Textarea:
              properties:
                elementClassAttribute: 'xxlarge'
Zurück