Formulare sind wesentlicher Bestandteil einer Webanwendung. Doch gerade beim Umstieg von einem anderen Framework kommt es in diesem Bereich zu Irritationen. Warum? Ein wesentlicher Unterschied besteht darin, dass es in Wicket nicht zwingend eine Ergebnisseite geben muss. Ich möchte das an einem Beispiel veranschaulichen.
Als erstes erstellen wir eine JavaBean in der das Formular die Daten ablegt:
package de.wicketpraxis.web.blog.pages.questions.migration.forms;
import java.io.Serializable;
public class FormBean implements Serializable
{
String _name;
public String getName()
{
return _name;
}
public void setName(String name)
{
_name = name;
}
}
Nichts besonderes. Die Bean hat das Attribut "Name". Erstellen wir eine Seite, die über ein Formular diese Bean mit Werten füllt:
package de.wicketpraxis.web.blog.pages.questions.migration.forms;
import java.io.Serializable;
import org.apache.wicket.markup.html.WebPage;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.model.CompoundPropertyModel;
public class MinimalFormPage extends WebPage
{
public MinimalFormPage()
{
Form<FormBean> form = new Form<FormBean>("form",new CompoundPropertyModel<FormBean>(new FormBean()));
form.add(new TextField<String>("Name"));
add(form);
}
}
Wie wir sehen, wird ein Formular eingebunden und in dieses Formular ein Textfeld für das Attribut benutzt. Damit ist dieses Beispiel funktionsfähig. Es macht nur nicht besonders viel. Was aber gut zu erkennen ist:
- es wird keine Ergebnisseite benötigt
- es muss keine Methode überschrieben werden, um die Eingabedaten in der Bean abzulegen
Das Markup ist ebenfalls recht einfach:
<html>
<head>
<title>MinimalFormPage</title>
</head>
<body>
<form wicket:id="form">
Name <input wicket:id="Name"><br>
<input type="submit" value="Absenden">
</form>
</body>
</html>
Interessant: der Submit-Button hat in diesem Beispiel keine Entsprechung als Wicket-Komponente. Das Formular wird trotzdem abgeschickt.
Komplexes Beispiel
Kommen wir nun zu einem etwas komplexeren Beispiel, dass eine Ergebnisseite verwendet. Dabei an dieser Stelle nocheinmal der Hinweis: die Ergebnisseite wird verwendet, weil wir das in diesem Beispiel so wollten. Alles was auf der Ergebnisseite dargestellt werden kann, könnte man auch ganz einfach auf der Seite darstellen, auf der auch das Formular eingebunden ist.
Als erstes erstellen wir die Ergebnisseite:
package de.wicketpraxis.web.blog.pages.questions.migration.forms;
import org.apache.wicket.PageParameters;
import org.apache.wicket.markup.html.WebPage;
import org.apache.wicket.markup.html.basic.Label;
public class ResultPage extends WebPage
{
public ResultPage(String name)
{
init(name);
}
public ResultPage(PageParameters pageParameters)
{
init(pageParameters.getString("Name"));
}
protected void init(String name)
{
add(new Label("name",name));
}
}
<html>
<head>
<title>ResultPage</title>
</head>
<body>
Name <span wicket:id="name"></span>
</body>
</html>
Die Seite besitzt zwei Konstruktoren. Der erste erwartet einen String als Parameter, der zweite wertet die Seitenparameter aus (wenn die Seite z.B. mit ?Name=klaus aufgerufen wird). Der Wert wird durch das Label zur Anzeige gebracht.
Jetzt die Formularseite:
package de.wicketpraxis.web.blog.pages.questions.migration.forms;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import org.apache.wicket.PageParameters;
import org.apache.wicket.markup.html.WebPage;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.markup.html.panel.FeedbackPanel;
import org.apache.wicket.model.CompoundPropertyModel;
public class KomplexFormPage extends WebPage
{
public KomplexFormPage()
{
add(new FeedbackPanel("feedback"));
Form<FormBean> form = new Form<FormBean>("form",new CompoundPropertyModel<FormBean>(new FormBean()))
{
@Override
protected void onSubmit()
{
// Variante 1
setResponsePage(new ResultPage(getModelObject().getName()));
// Variante 2
Map<String,String> map=new HashMap<String, String>();
map.put("Name", getModelObject().getName());
setResponsePage(ResultPage.class, new PageParameters(map));
// Variante ?
}
};
form.add(new TextField<String>("Name").setRequired(true));
add(form);
}
}
Wir haben in diesem Beispiel ein FeedbackPanel hinzugefügt, da wir auch das Textfeld zum Pflichtfeld gemacht haben. Ohne FeedbackPanel kommt sonst der Hinweis, dass man etwas eingeben muss, nicht zur Anzeige. Ansonsten haben wir die onSubmit-Methode überschrieben, die die Ergebnisseite aufruft. Dabei können wir zum einen eine Instanz der Seite erstellen, in dem wir (vorrausgesetzt es gibt einen passenden Konstruktor) den/die gewünschten Parameter direkt übergeben. Das wir in diesem Beispiel nur ein String übergeben, soll nicht darüber hinwegtäuschen, dass jedes beliebige (also auch weit komplexere) Objekte übergeben werden können.
Die zweite Variante verpackt den Parameter in einen Seitenparameter und springt die Seite dann über eine passende Url an. In diesem Fall werden natürlich die übergebenen Parameter für den Nutzer sichtbar. Das entspricht auch eher dem klassischen Verständnis einer Formularbehandlung in anderen Frameworks. Der Unterschied besteht allerdings schon darin, dass an dieser Stelle die Formularbehandlung bereits abgeschlossen ist und wir nur noch einmal absichtlich auf eine andere Seite springen.
Daher ist die letzte Variante auch nur mit einem Fragezeichen versehen. Wenn nichts dafür spricht, dass man eine wie auch immer geartete Ergebnisseite benötigt, kann man diese auch weglassen. Man sollte vielmehr darauf zurückgreifen, dass man Komponenten ein und ausblendet, wenn man das Formular nach erfolgreichem Ausfüllen nicht mehr anzeigen möchte.
Zusammenfassung
Ich hoffe, ich konnte zeigen, dass man sich vom dem klassischen Konzept einer Formularseite trennen muss und die Formularverarbeitung in Wicket ihre Entsprechung vermutlich eher in Swing findet.