Quicknavi |
|
Formulare
Artikel bewerten:
Bitte bewerten Sie den Artikel per Klick auf einen der angezeigten Sterne:
Zurück zum Artikel!
Das Adventure-PHP-Framework unterstützt die dynamische Generierung und Abstraktion von Formularen
out-of-the-box. Durch den generischen Tag-Parser können Formulare durch Tags in Templates und die
entsprechenden DOM-Objekte im Objektbaum der Präsentations-Schicht abgebildet werden. Dadurch ist
es möglich Formular-Elementen "interne Intelligenz" mitzugeben. Hierrunter fällt das
automatische Ausfüllen anhand eines URL-Parameters und die Validierung von Benutzereingaben. Dies
beiden Features können einfach durch die Definition des Verhaltens in den Templates gesteuert
werden und der Entwickler benötigt keine weiteren Hilfmittel und Logiken mehr.
1. Aufbau von Formularen
Formulare werden im Framework wie Templates behandelt und sind Kinder eines Baum-Knotens. Mit der
Methode __getForm() kann innerhalb eines Document-Controllers auf ein Formular
zugegriffen werden. Das Formular unterstützt folgende wichtige Funktionen:
-
addFormElement()
Fügt ein Formular-Element zum Formular hinzu. Die Methode ist für
die dynamische Generierung von Formularen gedacht.
-
addFormContent()
Fügt (HTML-/Text-)Inhalt zum Formular hinzu. Die Methode ist für
die dynamische Generierung von Formularen gedacht.
-
addFormContentBeforeMarker()
Fügt (HTML-/Text-)Inhalt vor einem Marker-Tag zum Formular hinzu. Die Methode ist für
die dynamische Generierung von Formularen gedacht.
-
addFormContentAfterMarker()
Fügt (HTML-/Text-)Inhalt nach einem Marker-Tag zum Formular hinzu. Die Methode ist für
die dynamische Generierung von Formularen gedacht.
-
addFormElementBeforeMarker()
Fügt ein Formular-Element vor einem Marker-Tag zum Formular hinzu. Die Methode ist für
die dynamische Generierung von Formularen gedacht.
-
addFormElementAfterMarker()
Fügt ein Formular-Element nach einem Marker-Tag zum Formular hinzu. Die Methode ist für
die dynamische Generierung von Formularen gedacht.
-
setPlaceHolder()
Füllt einen angegebenen Platzhalter mit einem Wert.
-
setAction()
Setzt das "action"-Attribut des Formulars.
-
getFormElementByName()
Gibt eine Referenz auf ein Formular-Objekt zurück.
-
getFormElementByID()
Gibt eine Referenz auf ein Formular-Objekt zurück.
-
getFormElementByObjectID()
Gibt eine Referenz auf ein Formular-Objekt zurück.
-
transformForm()
Erzeugt die HTML-Ausgabe eines Formular-Objekts und gibt diese zurück.
-
transformOnPlace()
Definiert, dass das Formular an der Stelle, an der es im Template-File definiert wurde ausgegeben
wird. Damit ist es nicht mehr nötigt, das Formular per transformForm() zu transformieren
und in einen Platzhalter einzusetzen.
Um ein Formular in einer Template-Datei zu definieren muss zuerst per
<core:addtaglib namespace="tools::form::taglib" prefix="html" class="form" />
vor der Verwendung hinzugefügt werden. Anschließend kann beispielsweise
ein Formular einer Login-Maske definiert werden:
<html:form name="AdminLogin" method="post" action="">
<form:placeholder name="LogInError" />
Benutzer: <form:text name="Username" class="eingabe_feld" style="width: 200px; margin-left: 20px;"
validate="true" button="AdminLogin" />
<br />
Passwort: <form:password name="Password" class="eingabe_feld" style="width: 200px; margin-left: 16px;"
validate="true" button="AdminLogin" />
<br />
<br />
<form:button name="AdminLogin" value="Login" class="eingabe_feld" style="margin-left: 227px;"/>
</html:form>
In Prosa: das Formular definiert die Attribute name, damit im Controller später
auf dieses zugegriffen werden kann, method um die Methode des Abschickens zu
definieren und action um die Ziel-URL zu definieren. Letzteres muss in der Template-
Datei nicht zwingend gesetzt werden, da die TagLib dieses selbst mit der aktuellen URL setzt oder
füllt, falls es nicht vorhanden ist.
Innerhalb des Formulars werden viel Formular-Elemente definiert: ein Platzhalter, für die Aufnahme
von Hinweistexten, ein Text- und ein Passwort-Feld und ein Button. Diese sind jeweils mit den unter
Standard-TagLibs beschriebenen Attributen
ausgestattet. Im Document-Controller kann nun per
$Form__AdminLogin = &$this->__getForm('AdminLogin');
eine Referenz auf das Formular geholt werden. Anschließend kann per
$Form__Placeholder_LogInError = &$Form__AdminLogin->getFormElementByName('LogInError'); $Form__Placeholder_LogInError->setPlaceHolder('Login failed!');
der Inhalt des Platzhalters manipuliert oder mit
if($Form__AdminLogin->get('isValid') && $Form__AdminLogin->get('isSent')){
// Aktion ausführen, die bei abgeschicktem und // valide ausgefülltem Formular passieren soll...
// end if }
abgefragt werden, ob das Formular abgeschickt wurden und die Eingaben valide sind.
Um das Formular auszugeben gibt es zwei Möglichkeiten: Ausgabe über einen im Template-File
definierten Platzhalter oder Verwendung von transformOnPlace():
function transformContent(){
...
// Formular transformieren und in einen Platzhalter einsetzen ... $this->setPlaceHolder('...',$Form__AdminLogin->tranformForm());
// ... oder das Formular an der Definitionsstelle ausgeben $Form__AdminLogin->tranformOnPlace();
...
// end function }
2. Validierung
Wie bereits erwähnt ist die Validierung von Formular-Feldern bereits out-of-the-box möglich.
Hierzu muss ein Formular-Feld lediglich um die Attribute
- validate
- validator
- button
wie unter Standard-TagLibs, Kapitel 2.3.,
beschrieben, erweitert werden. Für die Validierung des oben genannten Login-Formulars muss das
Textfeld wie folgt definiert werden:
<form:text name="Username" validate="true" button="AdminLogin" />
Wichtig ist die Angabe des Button-Namens, da das Formular erst nach dem Abschicken validiert werden
soll. Ist das Button-Attribut nicht gesetzt, wird von der TagLib ein Fehler ausgegeben. Zur
Ausgabe-Formatierung kann dieser Tag um weitere Attribute wie "class" und style" erweitert werden.
<form:text name="Username" class="eingabe_feld" style="width: 200px; margin-left: 20px;"
validate="true" button="AdminLogin" />
Ist das Attribut "validator" nicht gesetzt, so wird validiert, ob das Feld > 3 Zeichen enthält.
3. Manipulation von Formularwerten
Die Implementierung der Formular-TagLibs des Frameworks bringt einige Möglichkeiten zur
Manipulation von Formularelementen oder deren Werte mit. Die folgenden Kapitel zeigen häufig
auftretende Anwendungsbeispiele.
3.1. Vorbefüllung von Formularen
Zur Vorbefüllung von Formularen (z.B. in einem Bearbeiten-Dialog) können Methoden
getFormElementByID(), getFormElementByID() oder
getFormElementByObjectID() eingesetzt werden um eine Referenz auf ein Formular-Element
zu beziehen. Anschließend stehen die Standard-Methoden get() und
getAttribute(), bzw. set() und setAttribute() zur
Verfügung.
Die folgenden Codebox definiert ein Beispiel-Formular, das im anschließend
abgedruckten PHP-Code befüllt wird:
<core:addtaglib namespace="tools::form::taglib" prefix="html" class="form" />
<html:form name="UserEdit" method="post">
<strong>FirstName</strong>:
<form:text name="FirstName" validate="true" button="Edit" />
<br />
<strong>LastName</strong>:
<form:text name="LastName" validate="true" button="Edit" />
<br />
<br />
<form:button name="Edit" value="Save" />
<form:hidden name="userid" />
</html:form>
// Referenz auf das Form-Objekt beziehen $Form__Edit = &$this->__getForm('UserEdit');
// Referenz auf das Hidden-Feld beziehen und Wert befuellen $UserID = &$Form__Edit->getFormElementByName('userid'); $UserID->setAttribute('value','...');
// Referenz auf das FirstName-Feld beziehen und Wert befuellen $FirstName = &$Form__Edit->getFormElementByName('FirstName'); $FirstName->setAttribute('value','...');
// Referenz auf das LastName-Feld beziehen und Wert befuellen $LastName = &$Form__Edit->getFormElementByName('LastName'); $LastName->setAttribute('value','...');
3.2. Befüllen von Select-Feldern
Die Behandlung Select- und Multiselect-Feldern unterscheidet sich ein wenig von einfachen
Formular-Elementen. Das Framework stellt jedoch auch hier Methoden zur Verfügung, mit denen das
Befüllen von Feldern vereinfacht wird. Im nachfolgend aufgeführten Code wird ein Formular
vorausgefüllt, das zusätzlich zu den Standard-Text-Felder auch Auswahlfelder beinhaltet:
<core:addtaglib namespace="tools::form::taglib" prefix="html" class="form" />
<html:form name="UserCreate" method="post">
<strong>Salutation</strong>:
<form:select name="Salutation" />
<br />
<strong>FirstName</strong>:
<form:text name="FirstName" validate="true" button="Edit" />
<br />
<strong>LastName</strong>:
<form:text name="LastName" validate="true" button="Edit" />
<br />
<br />
<strong>Salutation</strong>:
<br />
<form:multiselect name="Group[]" validate="true" button="Edit" />
<br />
<br />
<form:button name="Edit" value="Save" />
<form:hidden name="userid" />
</html:form>
Wie in der Definition des Multiselect-Feldes Groups[] zu sehen ist, müssen bei
einem Multiselect-Feld die Namen eckigen Klammern versehen werden. Vergisst der Template-Entwickler
dies, wird eine entsprechende Fehlermeldung ausgegeben.
Der folgende PHP-Code befüllt das Formular:
// Referenz auf das Form-Objekt beziehen $Form__Create = &$this->__getForm('UserCreate');
...
// Referenz auf das Salutation-Feld beziehen und Wert befuellen $Salutation = &$Form__Create->getFormElementByName('Salutation');
for($i = 0; $i < count($Salutations); $i++){ $Salutation->addOption($Salutations[$i]['Value'],$Salutations[$i]['DisplayName']); // end for }
// Referenz auf das Groups[]-Feld beziehen und Werte befuellen $Group = &$Form__Create->getFormElementByName('Groups[]');
for($i = 0; $i < count($Groups); $i++){ $Group->addOption($Groups[$i]['Value'],$Groups[$i]['DisplayName']); // end for }
...
3.3. Auslesen von Formular-Elementen
Das Auslesen von Formular-Elementen gestaltet sich ähnlich wie das Befüllen. Eine
Besonderheit stellen auch hier die Einfach- und Mehrfachselektionsfelder dar. Das folgende Code-Beispiel
zeigt, wie die Werte des unter 3.1 dargestellten Formulars im DocumentController ausgelesen werden
können:
// Referenz auf das Form-Objekt beziehen $Form__Edit = &$this->__getForm('UserEdit');
// Hidden-Feld auslesen $UserID = &$Form__Edit->getFormElementByName('userid'); echo $UserID->getAttribute('value');
// FirstName-Feld auslesen $FirstName = &$Form__Edit->getFormElementByName('FirstName'); echo $FirstName->getAttribute('value');
// LastName-Feld auslesen $LastName = &$Form__Edit->getFormElementByName('LastName'); echo $LastName->getAttribute('value');
Um die selektierten Optionen eines Einfach- oder Mehrfachselektionsfeldes auszulesen, stehen die
Methoden getSelectedOption() und getSelectedOptions() zur
Verfügung. Die folgende Codebox zeigt den Anwendungsfall:
// Referenz auf das Form-Objekt beziehen $Form__Create = &$this->__getForm('UserCreate');
// Feld Salutation fuellen $Salutation = &$Form__Create->getFormElementByName('Salutation'); for($i = 0; $i < count($Salutations); $i++){ $Salutation->addOption($Salutations[$i]['Value'],$Salutations[$i]['DisplayName']); // end for }
// Salutation auslesen $Option = &$Salutation->getSelectedOption(); echo $Option->getAttribute('value').', '.$Option->get('Content');
// Feld Group fuellen $Group = &$Form__Create->getFormElementByName('Groups[]');
for($i = 0; $i < count($Groups); $i++){ $Group->addOption($Groups[$i]['Value'],$Groups[$i]['DisplayName']); // end for }
// Gruppen auslesen $SelectedGroups = &$Group->getSelectedOptions(); for($i = 0; $i < count($SelectedGroups); $i++){ echo $SelectedGroups[$i]->getAttribute('value').', '.$SelectedGroups[$i]->get('Content'); // end for }
4. Dynamische Formulare
In einigen Anwendungsfällen ist es notwenig, Formulare dynamisch nach Anforderung zu erstellen.
Hierzu besitzt die Implementierung der Formular-TagLib (html_taglib_form) die Methoden
- addFormElement()
- addFormContent()
und seit dem Release 1.7
- addFormContentBeforeMarker()
- addFormContentAfterMarker()
- addFormElementBeforeMarker()
- addFormElementAfterMarker()
an. Die ersten beiden Funktionen lassen sich dazu nutzen, Inhalte oder konkrete Formular-Elemente
an das Ende des Formulars anzuhängen. Die zu letzt genannten Methoden sind dazu gedacht, Inhalte
oder Formular-Elemente an konkreten Stellen zu platzieren. Zur Positionierung steht das
<form:marker />-Tag zur Verfügung. Das Tag selbst generiert keine Ausgabe,
sondern dient lediglich als Positionierungshilfe.
Die folgenden Kapitel sollen zeigen, wie ein dynamisches Formular zur Eingabe von Form-Koordinaten
(Dreieck, Quadrat, ...) realisiert werden kann. Je nach Auswahl des Typs sollen die jeweils notwenigen
Felder angezeigt werden. Bei Auswahl des Typs "square" werden vier Felder angezeigt ...
... und bei Auswahl von "triangle" drei:
4.1. Formular-Definition
Bei der Definition des Formulars sollte bereits bedacht werden, welche Art der Formular-Generierung
angestrebt wird. Kommen die Methoden addFormElement() und/oder addFormContent()
zum Einsatz, ist keinen Marker erforderlich. In diesem Beispiel wird jedoch ein Marker eingesetzt, da
das Formular bereits Inhalte besitzt, die nach den dynamisch erzeugten Elementen angezeigt werden
sollen.
Die folgende Code-Box zeigt das notwenige Formular mit einem Auswahlfeld. Bei der Implementierung
wurde auf CSS-Formatierung verzichtet um die wesentlichen Elemente besser hervorheben zu können.
Das Formular besteht dabei aus einem statisch definierten Auswahlfeld, das den Typ der geometrischen
Form vorgibt und aus einem Marker-Tag, der als Positionierungshilfe für die dynamisch erzeugten
Felder dient. Weiterhin wird ein DocumentController definiert, der die gewünschten Felder
dynamisch an der Stelle des Markers hinzufügt:
<@controller namespace="..." file="..." class="select_controller" @>
<core:addtaglib namespace="tools::form::taglib" prefix="html" class="form" />
<html:form name="type" method="post">
<table>
<tr>
<td>
Please choose the desired form type:
<form:select name="type">
<select:option value="triangle">triangle</select:option>
<select:option value="square">square</select:option>
</form:select>
</td>
<td>
<form:button name="submit" value="send" />
</td>
</tr>
<tr>
<td>
<form:marker name="fields" />
</td>
</tr>
</table>
</html:form>
4.2. Controller
Der DocumentController übernimmt im beschriebenen Beispiel die Generierung der abhängigen
Formularfelder, die je nach Auswahl angezeigt werden sollen. Hierzu wird im Controller zunächst
definiert, welche Formular-Felder für welchen Typ angezeigt werden. Anschließend wird
das Typ-Feld ausgewertet und das Formular mit Inhalten und Text-Feldern gemäß Typ
ergänzt. Die folgende Code-Box zeigt die Implementierung des DocumentControllers:
class select_controller extends baseController {
// specify form element container var $__FormElements = array();
function select_controller(){
// define form elements for the triangle $this->__FormElements['triangle'][] = array('label' => 'coord 1','name' => 'coordone'); $this->__FormElements['triangle'][] = array('label' => 'coord 2','name' => 'coordtwo'); $this->__FormElements['triangle'][] = array('label' => 'coord 3','name' => 'coordthree');
// define form elements for the square $this->__FormElements['square'][] = array('label' => 'coord 1','name' => 'coordone'); $this->__FormElements['square'][] = array('label' => 'coord 2','name' => 'coordtwo'); $this->__FormElements['square'][] = array('label' => 'coord 3','name' => 'coordthree'); $this->__FormElements['square'][] = array('label' => 'coord 4','name' => 'coordfour');
// end function }
function transformContent(){
// get form reference $Form = &$this->__getForm('type');
// get current decision $Select = &$Form->getFormElementByName('type'); $Option = &$Select->getSelectedOption(); if($Option === null){ $CurrentType = 'triangle'; // end if } else{ $CurrentType = $Option->getAttribute('value'); // end else }
// add form elements for($i = 0; $i < count($this->__FormElements[$CurrentType]); $i++){
// add label $Form->addFormContentBeforeMarker('fields',$this->__FormElements[$CurrentType][$i]['label'].': ');
// add text field (name attribute is present to enable validation and presetting!) $CurrentElementID = $Form->addFormElementBeforeMarker( 'fields', 'form:text', array('name' => $this->__FormElements[$CurrentType][$i]['name']) );
// configure further form element attributes $CurrentElement = &$Form->getFormElementByObjectID($CurrentElementID); $CurrentElement->setAttribute('style','width: 200px;');
// add a line break $Form->addFormContentBeforeMarker('fields','<br />');
// end for }
// display form $Form->transformOnPlace();
// end function }
// end class }
4.3. Wichtige Hinweise
Ein APF-Formular-Element benötigt bereits bei der Erstellung des Objekts die Information über
den Namen des Feldes. Ist dieser nicht bekannt, kann es nicht vorausgefüllt oder validiert werden.
Um die Presetting und Validierung von Formular-Elementen nutzen zu können besitzen die Methoden
addFormElement(), addFormElementBeforeMarker() und addFormElementBeforeMarker()
einen optionalen, dritten Parameter. Dieser erwartet eine assoziative Liste von Tag-Attributen, die
dem Formular-Tag bei der Erstellung mitgegeben werden. Es daher sinnvoll, der Methode mindestens
den Namen des Feldes in der Form
array(
'name' => 'current_name'
)
als drittes Argument mitzugeben. Dies kann unter Umständen auch für die spätere
Adressierung der Objekte über die Methoden getFormElementByName() und
getFormElementByID() von Interesse sein.
Kommentare
Möchten Sie den Artikel eine Anmerkung hinzufügen, oder haben Sie ergänzende Hinweise? Dann können Sie diese hier einfügen. Die bereits verfassten Anmerkungen und Kommentare finden Sie in der untenstehenden Liste.
«
1
»
Einträge/Seite: |
5 |
10 |
15 |
20 |
|
1
|
Christian
12.11.2008, 19:27:17
|
Zu Punkt 4.3. ist auch die Diskussion unter http://forum.adventure-php-framework.org/de/viewtopic.php?f=8&t=66#p365 noch interessant.
|