Formulare in den Tabs

Prinzipieller Aufbau des UI aus Go Templates

Die Formulare sind aus mehreren Templates auf unterschiedlichen Ebenen zusammengestellt, um eine möglichst hohe Wiederverwendung zu erreichen. Hier werden jetzt nach dem Überblick die unteren beiden Ebenen genauer betrachtet.

  1. Template-Ebene: Hier wird das <form> Element angelegt. Es enthält
    • ein Template mit einem <input type='hidden'>  zum Schutz gegen Cross Site Request Forgery,
    • untergeordnete Templates mit den Form Input Elementen usw.,
    • die für dieses Formular relevante Buttons,
    • ein wenig JavaScript zur Initialisierung ( $(document).ready( function() { ...} ) und Handler für die Buttons.
  2. Template-Ebene: Zusammenfassung der Eingabefelder mit Beschriftung, Bootstrap-Layout usw.
  3. Template-Ebene: Dafür habe ich die Templates forminput und formselect geschrieben, die jeweils ein <input> bzw. ein <select> Element mit den ganzen Beschriftungen, Layouts, Validatoren usw. zusammenfassen. Ob das die beste Lösung ist, kann sicher diskutiert werden. Aber mir hat es nicht gefallen, viele ähnliche Felder zu haben, die bei der Optimierung von Layout und Funktion immer wieder einzeln verändert werden müssen.

Um mit der dritten Ebene arbeiten zu können, müssen eigene Funktionen für die Verwendung in den Templates implementiert werden.

Eigene Funktionen für Go Templates

Eine Beschränkung bei Go Templates besteht darin, dass ein Template nur maximal einen Parameter übergeben bekommt. Das kann zwar eine Go map oder struct sein, aber es schränkt die Flexibilität ein. So kann man nicht einfach literale Konfigurationsparameter hinzufügen, um beispielsweise die Spaltenbreite eines Eingabefeldes festzulegen. Es macht auch wenig Sinn, derartige Layout Parameter im Handler festzulegen, weil damit das Prinzip der Trennung von Inhalt und Layout maximal verletzt würde. Als Ausweg bietet Go die Möglichkeit, eine map mit Funktionen bei den Templates zu registrieren. Damit können z.B. zusätzlich literale Werte zu einer Map hinzugefügt werden.

Die func map lässt sich folgendermaßen in die Templates einbinden:

Die Funktionen sind in der Datei view/viewutils.go implementiert und auf godoc.org dokumentiert.

Eine weitere Einschränkung ist, dass Zeilenumbrüche innerhalb der {{ … }} Template Ausdrücke nicht zulässig sind. Daher können Zeilen mit vielen Parametern sehr lang und unübersichtlich werden.

Implementierung

Input Elemente

Die Templates für Input-Elemente sind in FormElements.go.html implementiert. Als Beispiel hier das Template für Bootstrap-formatierte <input> Elemente:

Die wesentliche Idee ist, dass dieses Template mit einer Go map aufgerufen wird, die vorher mit den Funktionen der func map zusammengestellt wurde. Die Parameter, die das Template braucht, sind mit entsprechenden keys in der map abgelegt. Die Dokumentation beschreibt die einzelnen Parameter (= map-Einträge). Als optional gekennzeichnete Parameter können weggelassen werden, dann werden Standardwerte verwendet. Der eigentliche HTML-Code im Template orientiert sich an den Beispielen im Bootstrap 3 Tutorial bei Tutorial Republic.

Hinweis: Eine Validierung mit Regular Expressions funktioniert bei dieser Version nicht.

Eine struct könnte statt der map auch verwendet werden, jedoch habe ich dafür keine Funktionen geschrieben, weil maps sehr viel einfacher dynamisch angelegt werden können.

Das Template formselect ist analog aufgebaut.

Verwendung für Eingabemasken

Als Beispiel soll das Stammdatenformular (Datei Registration.go.html) dienen, das sowohl bei der Registrierung von Bewerbern als auch beim Änderung von Stammdaten verwendet wird.

90
Mit der Funktion dict wird in Variable $defuser eine map angelegt. Die Parameter von dict sind immer abwechselnd key und value für die map. $defuser enthält Standardwerte, die für die folgenden Template-Aufrufe verwendet werden können.
91, 92 und weitere
Mit der Funktion mergedict werden zwei maps zu einer Neuen zusammengefügt, die als Parameter an das Template übergeben wird.
95, 96
Für die Lesbarkeit ist es eventuell besser, erst zwei map Variablen anzulegen und diese dann im Template-Aufruf zusammenzufügen.
105, 106
Die <select> Listbox wird analog zu den <input> Templates aufgebaut.
Fazit

Der entstandene Template-Code ist gewöhnungsbedürftig, aber viel kürzer als die individuelle Implementierung aller Eingabeelemente. Die entstandenen 36 Zeilen Code ersetzen 122 Zeilen in der Implementierung ohne Templates.

 

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.