Neuerungen für Entwickler in WoltLab Suite 5.2

Form Builder

Vor WoltLab Suite Core 5.2 musste bei der Erstellung von Formularen ähnlicher Code immer wieder geschrieben werden: die Eigenschaften des PHP-Controllers deklarieren, in die die Eingabewerte eingelesen werden, die entsprechenden Werte aus den Request-Daten auslesen, diese Werte validieren, sie einer `IDatabaseObjectAction`-Instanz übergeben, um das relevante Objekt zu erstellen oder zu bearbeiten, und die Eingabewerte abschließend Template-Variablen zuweisen. Im Template benötigte jedes Eingabefeld ein eigenes Form-Element, das im Allgemeinen bis auf das Label und die Beschreibung sehr viel Code mit ähnlichen Feldern gemeinsam hat.

Mit der neuen Version von WoltLab Suite Core haben wir eine neue Komponente hinzugefügt, die die Erstellung von Formularen deutlich vereinfacht: Form Builder. Mit Form Builder muss im Wesentlichen nur ein PHP-Objekt pro Eingabefeld erstellt werden und lediglich eine Zeile Template-Code für das gesamte Formular geschrieben werden.

Der folgende PHP-Code erstellt ein Formular mit zwei Eingabefeldern, einem einfachen Text-Feld, das ausgefüllt werden muss und dessen Wert nicht foo sein darf, und eine Ja/Nein-Auswahl (was einem boolschen Wert entspricht). Diese beiden Felder befinden sich in einem Abschnitt des Formulars, der mit wcf.global.form.data überschrieben ist.

Formular-Controller, die Form Builder verwenden, müssen von der Klasse AbstractFormBuilderForm erben und sie müssen sowohl die Werte von $objectActionClass und $formAction setzen, als auch createForm() wie oben gezeigt überschreiben. Die save()-Methode wird automatisch aufgerufen und führt die relevante Aktion, create oder update, mit einem $objectActionClass-Objekt aus.

Im Template ist es ausreichend die getHtml()-Methode des Formulars aufzurufen:

Code
{@$form->getHtml()}

Das Ergebnis ist das folgende Formular:

WoltLab Suite 5.2 wird bereits viele fertige Eingabefeld-Klasse mitliefern, die für die meisten Formulare ausreichend sein werden. Für spezielle Felder können Sie natürlich eigene Felder implementieren, die Sie dann auch direkt in Ihrem Paket wiederverwenden können.

Abschließend möchten wir noch kurz vorstellen, wie Sie innerhalb Ihres Formulars Abhängigkeiten zwischen Feldern definieren. In komplexeren Formularen kann es vorkommen, dass bestimmte Teile des Formulars nur dann verfügbar sein sollen, wenn ein bestimmtes Feld einen bestimmten Wert hat. Mit Form Builder lässt sich eine solche Abhängigkeit mit nur wenigen Zeilen PHP-Code realisieren:

PHP
$foo->addDependency(
    ValueFormFieldDependency::create('bar')
        ->field($bar)
        ->values(['baz'])
);

In diesem Fall ist das $foo-Feld nur dann verfügbar, also im Formular sichtbar, wenn der aktuelle Wert des $bar-Feldes baz ist.

Form Builder kann selbstverständlich nicht nur in Controllern verwendet werden. Beispielsweise ist es auch in Dialogen möglich Formulare mit Form Builder zu erstellen. In diesen Fällen muss jedoch das IFormDocument-Objekt manuell erstellt werden (AbstractFormBuilderForm erledigt dies automatisch):

Im obigen Code-Beispiel wird das von FooAction::getFooForm() generierte Formular nach einem Klick auf den openFooFormButton-Button in einem Dialog angezeigt. Die eingegebenen Daten werden nach dem Absenden des Formulars von FooAction::submitFooForm() verarbeitet. Bei einer fehlerhaften Validierung der Daten wird das Formular mit der entsprechenden Fehlermeldung wieder angezeigt wird. Bei einer erfolgreichen Validierung werden die Rückgabewerte der FooAction::submitFooForm() an successCallback übergeben.

Die Interfaces und Klassen von Form Builder sind umfangreich dokumentiert und wir werden unsere Entwickler-Dokumentation mit allgemeinen Informationen zu Form Builder und zur Migration alter Formulare zu neuen Form-Builder-Formularen aktualisieren.

Neue Entwickler-Werkzeuge

In der neuen Version haben wir außerdem viele neue Funktionen zu den Entwickler-Werkzeugen, die in der Administrationsoberfläche verfügbar sind, hinzugefügt.

So ist es nun möglich, Pakete direkt von der Projektliste aus zu installieren, ohne vorher ein Archiv erstellen und dann das Paket manuell in der Paketverwaltung hochladen zu müssen. Stattdessen verwenden die Entwickler-Werkzeuge direkt die Originaldateien aus dem Projekt-Verzeichnis.

Wenn ein neues Projekt angelegt wird, kann zusätzlich zum Import eines vorhandenen Pakets auch ein neues Paket erstellt werden. Dafür werden zusätzliche Formularfelder angezeigt, die alle Informationen aus der package.xml-Datei des Pakets abfragen. Beruhend auf diesen Daten wird dann auch eine package.xml-Datei für das neue Projekt erstellt. Analog zu dieser neuen Funktion beim Erstellen von neuen Projekten ist es nun auch möglich die `package.xml`-Datei vorhandener Projekte mit einer grafischen Benutzeroberfläche zu bearbeiten, die die Eingaben vor der Speicherung überprüft und so sicherstellt, dass die package.xml-Datei gültig ist.

Eine weitere neue und ziemlich umfrangreiche neue Funktion in den Entwickler-Werkzeuge ist die Möglichkeit Package Installation Plugin-Einträge mit einer grafischen Benutzeroberfläche hinzuzufügen, zu bearbeiten und zu löschen.

Die folgende animierte Grafik zeigt das Formular zum Hinzufügen eines neues Objekttypen zu einem Paket und demonstriert die Stärken der grafischen Benutzeroberfläche, da sich das Formular an die ausgewählten Objekttyp-Definition anpasst und alle zusätzlichen Felder anzeigt, die für die ausgewählte Objekttyp-Definition relevant sind.

Wenn ein Eintrag gelöscht wird, wird er aus der Datenbank entfernt und die Import-Anweisung wird gelöscht. Falls das Package Installation Plugin die Löschung von Einträgen unterstützt, ist es auch möglich, eine explizite Lösch-Anweisung ergänzen zu lassen.

Bitte beachten Sie, dass nur Package Installation Plugins, die das IGuiPackageInstallationPlugin-Interface implementieren, von der grafischen Benutzeroberfläche unterstützt werden.

Sowohl das Formular zum Hinzufügen neuer Projekte, als auch die Formulare zum Hinzufügen und Bearbeiten von Package Installation Plugin-Einträgen wurden mit Form Builder erstellt.


Damit ist unsere Vorstellungsreihe zu WoltLab Suite 5.2 zu Ende und wir hoffen, dass die vorgestellten Änderungen Ihr Interesse geweckt haben. Vor der Veröffentlichung der finialen Version werden wir noch eine Übersicht mit vielen der weiteren Änderungen in Version 5.2 bereitstellen.

Kommentare 52

@Devon Du kannst einen eigenen FormFieldValidator hinzufügen, der sich um die Dateityp-Validierung kümmert.

Auch wenn mein letzter Beitrag hier länger her ist, Dateitypen lassen sich dort nicht festlegen innerhalb des Feldes UploadFormField?

Ja, einfach nicht auf imageOnly setzen, dann können beliebige Dateien hochgeladen werden.

Nur zum Verständnis: Mit dem Form Builder lässt sich auch eine Upload Form einrichten, die nicht zwingend wie im Beispiel (ok, vielleicht habe ich das auch falsch verstanden) Bilder als Dateien voraussetzt? https://docs.woltlab.com/php_api_form_b…uploadformfield

Oops, da war ich, aber ich habe es tatsächlich übersehen. Sorry.

Die Interfaces und Klassen von Form Builder sind umfangreich dokumentiert und wir werden unsere Entwickler-Dokumentation mit allgemeinen Informationen zu Form Builder und zur Migration alter Formulare zu neuen Form-Builder-Formularen aktualisieren.

Gibt es da mittlerweile etwas?

Kurz: Eine tolle Sache! Freue mich schon darauf da selbst Hand anzulegen. Spezielle individuelle Formulare werden bei öfter nachgefragt als man denkt. Schön wenn man da künftig mit wenig Aufwand eines stricken und in ein Plugin verpacken kann. :thumbup:

wenn der Vorschläge hier gepostet werden,

Es war eine Frage und kein Vorschlag. Und die habe ich gestellt, weil ich jetzt Entscheidungen bezüglich der Anpassung meiner Erweiterungen an WSC 5.2 treffen muss und nicht unbestimmte Zeit auf ein Label zu einem Vorschlag warten kann.

Das heißt nicht, dass das ganze nicht geplant ist. Es ist für uns einfach unübersichtlich, wenn der Vorschläge hier gepostet werden, diese gehen dann einfach zu schnell unter, falls es nicht sofort jemand von uns umsetzt. Außerdem ist es für unser Backlog ganz gut, wenn wir was dafür haben.

Ich bin dem Vorschlag nicht abgeneigt (auch nicht, für die jetzt anstehende Version).

Ansonsten, ist ein Validator, der nach der Dateigröße und ggf. der Bildgröße validiert ganz schnell geschrieben (auf Basis des Uploads für Reaktions-Typen / ungetestet):

Eine IUploadFileValidationStrategy zu übergeben halte ich für nur begrenzt sinnvoll, da wir dann die neue UploadFile-Klasse auf die alte umbiegen müssen, was nur begrenzt sinnvoll ist, gerade da die Validation mit einem eigenem Validator bei FormFields super einfach und übersichtlich ist.

Grüße

Josh

Wieso kann man nicht einfach ein IUploadFileValidationStrategy an UploadFormField übergeben?

Also nicht geplant. Dann lieber eine eigene Umsetzung ;)

@UdoZ Dafür bitte einen eigenen Vorschlag erstellen.

WoltLab Suite 5.2 wird bereits viele fertige Eingabefeld-Klasse mitliefern, die für die meisten Formulare ausreichend sein werden.

Wie z.B. UploadFormField.

Ist hier geplant, Limits für die Dateigröße sowie eine Skalierung für Bilder, bzw. zumindest eine Begrenzung der Dimensionen zu ergänzen?

Siehe Nutzung bei Reaktionen; x MByte große Reaktions-Dateien sind nicht wirklich prickelnd...

Das verstehst du falsch, Profilfelder sind nicht auf dem neuen Form Builder basierend aus kompatibilitätsgründen.

Schade, wäre aber für Profilfelder auch echt gut, vor allem weil ich nicht der einzige bin der das haben mag.... :(

Ist es möglich dem Formular und […] Eltern-Elemente (dt/dd) CSS-Klassen zu vergeben?

Ja.

Ist es möglich dem Formular und den Inputfelder bzw. besser den Eltern-Elemente (dt/dd) CSS-Klassen zu vergeben? Das würde das Styling erleichtern, vor allem bei Endanwendungen.

Das verstehst du falsch, Profilfelder sind nicht auf dem neuen Form Builder basierend aus kompatibilitätsgründen.

Kann man damit nun Profilfelder erstellen welche nun abhängig sind. Heißt ich wähle beim ersten Feld X aus und bekomme dann im zweiten Feld alles passend zum ersten angezeigt? Oder verstehe ich das falsch?

Ich bin gerade nur mobil unterwegs, da ist GitHub schwierig. :P

insertBefore der Vollständigkeit halber wäre auch toll. :D

Rate mal zu welcher Funktion diese Zeile gehört ;)

insertBefore der Vollständigkeit halber wäre auch toll. :D

Aber das macht das Feature schon mehr deutlich flexibler als die bisherigen Formulare. :)

Da kommt mir die Frage: Kann ich ein neues Feld nachträglich per EL direkt unter bzw nach ein bestimmtes Feld platzieren? Ggf. mit nicevalue.

https://github.com/WoltLab/WCF/co…1f5d26e204204db

Jetzt gehts^^

Da kommt mir die Frage: Kann ich ein neues Feld nachträglich per EL direkt unter bzw nach ein bestimmtes Feld platzieren? Ggf. mit nicevalue.

Der Event-Listener muss Zugriff auf das IFormDocument-Objekt haben und kann dann mit

PHP
$form->getNodeById('foo')->addValidator(…);

einen neuen Validator hinzufügen.

Wie wirkt sich das eigentlich auf die Events auf? Z. B. Ich möchte zu einem bestehenden Feld eine weitere, eigene Validierung hinzufügen über einen eventlistener in Bezug auf den Form builder?

Ich habe 2 Dropdowns. Abhängig davon was im ersten Dropdown ausgewählt wurde, ändert sich der Inhalt des zweiten Dropdowns.

Das lässt sich so umsetzen, dass man nicht ein zweites Feld erstellt, sondern für jeden relevanten Wert (oder für jede relevante Wertemenge) des ersten Feldes ein separates zweites Feld erstellt und diesen dann Dependencies auf den Wert des ersten Feldes hinzufügt.