Neos Workshop Teil 4 - Formulare erstellen mit dem Neos Form Framework

Daniel Lienert
Daniel Lienert hat neben seinen Aufgaben als ScrumMaster auch eine großen Leidenschaft für gute Softwarearchitektur und performante Systeme.

Mit dem Neos Form Framework, welches bereits in der Neos Basisinstallation mit installiert wird, können einfache Kontaktformulare sowie auch komplexe, mehrseitige Formulare mit Validierungen durchgeführt werden. Außerdem bietet es diverse Erweiterungspunkte für die Anpassung an die eigene Anforderung.

In diesem Teil des Workshops zeige ich – passend zum bisherigen Thema – wie sich mit dem Form Framework ein Formular zur Buchung einer Weinprobe umsetzen lässt. Dabei baut auch dieser Workshop Teil auf die bisher erschienene Teile auf. Die Gesamtübersicht auf den hierfür nötigen Code findet sich wie immer im Github Repository zum Workshop.

Übersicht der bereits erschienene Workshop-Teile

Die folgenden Teile des  Neos-Workshops existieren bisher. Die dort erarbeitete Seite dient als Grundlage für diesen Workshop-Teil:

Formulare definieren

Formulare werden mittels YAML Dateien konfiguriert. Jede Form Definition besteht dabei aus den folgenden Teilen:

  • Im Kopfbereich des Formulars werden grundlegende Angaben wie Identifier und Label der Form definiert. 
  • Der Bereich der "renderables" – definiert die Formularfelder, welche sich über mehrere Sections auf einer Seite und auf mehreren Formularseiten verteilen lassen.
  • Zum Schluss werden die "finishers" definiert – sie legen fest, wie nach Absenden des Formulars die eingegebenen Daten verarbeitet werden sollen.

Für die Definition unseres Formulars legen wir in einem zu erstellenden Verzeichnis Resources/Private/Form/, eine neue Datei registration-form.yaml an.

Die Definition der Form beginnt zunächst mit den allgemeinen Angaben, wie dem eindeutigen Identifikator und einem sprechenden Namen. 

Darauf folgt die Definition der zu rendernden Elemente, welche verschachtelt angegeben werden können. Sogenannte Container-Elemente können verwendet werden, um das Formular zu strukturieren. Die Container-Elemente enthalten dann die eigentlichen Formularfelder.

Das oberste "renderable" definiert die Seite des Formulars mit dem strukturgebenden Typ TYPO3.Form:Page. Die Seite hat wiederum einen eigenen Abschnitt "renderables" mit dem die nächste Ebene an Elementen – in unserem Fall direkt die Formularfelder – definiert werden.

Im Beispiel werden einfache Textfelder für Name und E-Mail verwendet, ein Mehrzeilenfeld für den Kommentar und ein Select-Feld zur Auswahl der Veranstaltung. Jedes Element benötigt einen eindeutigen Identifier, über den auch später auf die Benutzereingaben zugegriffen werden kann. Darüber hinaus stehen weitere Optionen zur Konfiguration der Felder zur Verfügung. 

Durch die Angaben von Validatoren können Pflichtfelder definiert sowie Benutzereingaben überprüft werden. Im Beispiel verwenden wir den Validator TYPO3.Flow:NotEmpty zur Festlegung von Pflichtfeldern. Der TYPO3.Flow:EmailAddress Validator prüft die Eingabe auf eine korrekte Adresse.

type: 'TYPO3.Form:Form'
identifier: 'registration-form'
label: 'Anmeldung zur Weinprobe'
renderingOptions:
  submitButtonLabel: 'Anmelden'
renderables:
  -
    type: 'TYPO3.Form:Page'
    identifier: 'registration'
    renderables:
      -
        type: 'TYPO3.Form:SingleSelectDropdown'
        identifier: 'date'
        label: 'Datum'
        properties:
          options:
            'September 2016': 'Weinprobe September 2016'
            'Oktober 2016': 'Weinprobe Oktober 2016'
            'November 2016': 'Weinprobe November 2016'
      -
        type: 'TYPO3.Form:SingleLineText'
        identifier: 'name'
        validators:
          - identifier: 'TYPO3.Flow:NotEmpty'
        properties:
          placeholder: 'Name'
      -
        type: 'TYPO3.Form:SingleLineText'
        identifier: 'email'
        validators:
          - identifier: 'TYPO3.Flow:NotEmpty'
          - identifier: 'TYPO3.Flow:EmailAddress'
        properties:
          placeholder: 'E-Mail'
      -
        type: 'TYPO3.Form:MultiLineText'
        identifier: 'comment'
        properties:
          placeholder: 'Kommentar'
          rows: '3'

Formular Definition in Resources/Private/Form/registration-form.yaml

Über die im Beispiel verwendeten Felder hinaus, sind im Form Framework aber noch viele weitere Elemente und Validatoren definiert und können direkt verwendet werden.

Strukturelemente

TypBeschreibung
TYPO3.Form:PageEine Formularseite, ein mehrseitiges Formular ist möglich.
TYPO3.Form:SectionSection innerhalb einer Formularseite.

 

Spezielle Eingabefelder

TypBeschreibung
TYPO3.Form:DatePickerEine Formularseite, ein mehrseitiges Formular ist möglich.
TYPO3.Form:FileUploadSection innerhalb einer Formularseite.
TYPO3.Form:StaticTextAusgabe eines statischen Textes.

Standard Eingabefelder

TypBeschreibung
TYPO3.Form:SingleLineTextEinfaches Textfeld.

TYPO3.Form:Password

TYPO3.Form:PasswordWithConfirmation

Einfache Passworteingabe.

Passworteingabe mit Bestätigungsfeld.

TYPO3.Form:MultiLineTextMehrzeiliger Text. 
TYPO3.Form:CheckboxEinzelnes Checkbox Feld.
TYPO3.Form:SingleSelectDropdownDropdown Feld.
TYPO3.Form:SingleSelectRadiobuttonsRadio Button.
TYPO3.Form:MultipleSelectDropdownSelect-Liste für Mehrfachauswahl.

TypBeschreibung
TYPO3.Flow:NotEmptyFeld darf nicht leer sein. Damit wird ein Pflichtfeld definiert.
TYPO3.Flow:DateTimeRangeMit den options earliestDate und latestDate wird der valide Zeitraum festgelegt.
TYPO3.Flow:AlphanumericAlphanumerische Zeichen können verwendet werden.
TYPO3.Flow:TextText enthält keine XML Tags.
TYPO3.Flow:StringLengthMit den options minimum und maximum kann die nötige Längenbegrenzung angegeben werden.
TYPO3.Flow:EmailAddressValidiert auf eine korrekte E-Mail-Adresse .
TYPO3.Flow:IntegerPrüft auf Ganzzahl.
TYPO3.Flow:FloatPrüft auf eine valide Float-Zahl.
TYPO3.Flow:NumberRangePrüft auf eine Ganzzahl in einem Gültigkeitsbereich, welcher mit den options minimum und maximum angeben wird.
TYPO3.Flow:RegularExpressionPrüft gegen einen regulären Ausdruck aus der option regularExpression.

Formular einbinden

Mit der obigen Konfiguration kann das Formular bereits auf der Seite eingebunden werden. Dazu muss der Speicherpfad der Formulare geändert werden, so dass die Formular-Konfigurationen in unserem eigenen Site Packages gesucht werden. Unter Configuration in unserem Site Package legen wir dazu eine Settings.yaml an und fügen die folgende Konfiguration ein:

TYPO3:
  Form:
    yamlPersistenceManager:
      savePath: 'resource://WL.WeinLaden/Private/Form/'

Configuration/Settings.yaml

Zusätzlich muss unser Formular im Neos Formular NodeType als Option hinzugefügt werden, damit dieses im Inspektor ausgewählt werden kann. 

'TYPO3.Neos.NodeTypes:Form':
  properties:
    formIdentifier:
      ui:
        inspector:
          editorOptions:
            values:
              'registration-form':
                label: 'Anmeldung zur Weinprobe'

Configuration/NodeTypes.yaml

Finishers - was soll beim Absenden des Formulars passieren?

Was nach dem Absenden mit den Formulardaten passieren soll, wird mit Finisher definiert. Die beiden Finisher werden in der gleichen Datei wie auch alle anderen Angaben zum Formular definiert. 

Mit dem TYPO3.Form:Confirmation geben wir den Text an, welcher nach erfolgreichem Absenden des Formulars anstelle des Formulars angezeigt wird. Im Text, welchen wir mit der Option message definieren, können wir auch Angaben des Benutzers verwenden.

Der zweite Finisher vom Typ TYPO3.Form:Email versendet die Formulareingaben danach per E-Mail. Um diesen Finisher zu verwenden, muss zusätzlich das PHP Paket "SwiftMailer" installiert werden – dieser Schritt wird im nächsten Abschnitt erklärt.

Alle wichtigen Angaben der E-Mail, wie Ziel- und Absenderadresse und Betreff können dem Finisher direkt per Optionen übergeben werden. Der eigentliche E-Mail-Text wird in einer eigenen Datei gehalten, um die YAML Datei nicht unnötig aufzublähen. In diesem Beispiel senden wir eine Plaintext E-Mail, dessen Inhalt aus der Datei Resources/Private/Templates/Mail/Registration.txt gelesen wird.


finishers:
  -
    identifier: 'TYPO3.Form:Confirmation'
    options:
      message: >
        <h3>Vielen Dank für Ihre Anmeldung!</h3>
        <p>Wir freuen uns, Sie bei unserer Weinprobe im {formState.formValues.date} begrüßen zu dürfen.</p>
        <p>Ihr Weinladen Team</p>
  -
    identifier: 'TYPO3.Form:Email'
    options:
      templatePathAndFilename: 'resource://WL.Weinladen/Private/Templates/Mail/Registration.txt'
      subject: 'Neue Anmeldung zur Weinprobe'
      recipientAddress: 'anmeldung@weinladen'
      recipientName: 'Weinladen'
      senderAddress: 'no-reply@weinladen'
      senderName: '{name}'
      replyToAddress: 'no-reply@weinladen'
      format: 'plaintext'

Die konfigurierten Finisher in Resources/Private/Form/registration-form.yaml verarbeiten die Formulardaten.

Hallo liebes Weinladen Team,

eben ging eine neue Anmeldung für die Weinprobe im {form.formState.formValues.date} ein:

Name:     {form.formState.formValues.name}
E-Mail:   {form.formState.formValues.email}
Kommentar:{form.formState.formValues.comment}

Viele Grüße

Definition des Mailtextes in Resources/Private/Templates/Mail/Registration.txt

Neben den oben verwendeten Finishern bring das Form Framework noch weitere Möglichkeiten der Verarbeitung der Formdaten mit. Natürlich können auch eigene Klassen erstellt und an dieser Stelle zur Verarbeitung genutzt werden.

TypBeschreibung
TYPO3.Form:ConfirmationZeigt nach dem Absenden einen konfigurierbaren Text an.
TYPO3.Form:EmailVersendet einen E-Mail mit dem Inhalt des abgesendeten Formulars.
TYPO3.Form:FlashMessageZeigt eine beliebige Flash-Message nach dem Absenden an.
TYPO3.Form:RedirectLeitet die Eingaben nach dem Absenden auf einen Controller aus einem beliebigen anderen Package um.

Formular als E-Mail versenden mit Swiftmailer

Der E-Mail-Finisher verwendet das PHP Paket SwiftMailer um E-Mails zu versenden. Dieses Package muss per composer installiert werden. In der Neos Box im Verzeichnis /var/www fügen fügen wir diese Package mit dem folgenden Befehl der bestehenden Installation hinzu:

composer require typo3/swiftmailer:5.3.1

Während der Entwicklungsphase ist es aber recht unpraktisch, E-Mails wirklich zu versenden. Denn zur Prüfung des Inhalts muss so immer auf den Versand und den Abruf des Mailclients gewartet werden.
Einfacher ist es, die E-Mail lokal zu speichern. Dazu konfigurieren wir den Swiftmailer für die Ablage des Mailinhalts in einer lokalen Datei im MBox Format. Da dies nur im Development-Context, aber natürlich nicht im Live-Betrieb passieren soll, nehmen wir diese Einstellung in einer neuen Datei unter Configuration/Development/Settings.yaml vor:

TYPO3:
  SwiftMailer:
    transport:
      type: 'TYPO3\SwiftMailer\Transport\MboxTransport'
      options:
        mboxPathAndFilename: '%FLOW_PATH_DATA%/last-mail.mbox'

Configuration/Development/Settings.yaml

Die E-Mail kann nun direkt nach dem Absenden in der Datei /var/www/Data/last-mail.mbox ausgelesen werden. Beispielsweise mit dem Befehl "cat":

cat /var/www/Data/last-mail.mbox

Anzeigen der generierten E-Mail in der Entwicklerbox

Ich hoffe dieser Workshop Teil konnte vermitteln, wie mit dem Neos Form Framework einfach Formulare erstellt werden können. Den kompletten, dazu nötigen Code findest du wie immer auf unserem github Repository.  Eine momentan noch etwas rudimentäre, aber ständig erweiterte Dokumentation befindet sich auch auf ReadTheDocs. Für Fragen und Anmerkungen zu diesem Tutorial kann das Kommentarfeld unten gerne genutzt werden. 

Autor: Daniel Lienert

Kommentare

Bisher wurden keine Kommentare eingereicht.


Weitere Beiträge

19. August 2016

Anzeigen dynamischer Seiteninhalte im Zusammenspiel mit dem Zurück-Button

In Zeiten von dynamisch nachgeladenem Seiteninhalt kommt es häufiger vor, dass ein Zurückspringen auf … mehr

21. Juni 2016

Agile Coach Camp 17.-19. Juni 2016 in Rückersbach

Es waren einmal zwei ScrumMasterinnen bei punkt.de, die sich nach Fortbildung und Inspiration sehnten. … mehr