Webanwendungen ohne Formulare gibt es nicht. Dabei ist die korrekte Formularbehandlung alles andere als trivial. Zum Glück bietet Wicket eine ausgezeichnete Unterstützung für Formulare, die kaum Wünsche offen lässt. Doch auch mit Wicket sind ein paar Dinge zu beachten, um die verschiedenen Interaktionsmöglichkeiten des Nutzers korrekt zu verarbeiten.
Wicket bietet die Möglichkeit, neben dem normalen Abschicken eines Formulars auch auf die angeklickten Submit-Buttons reagieren zu können. Damit man aber auch zuverlässig unterscheiden kann, ob der Nutzer das Formular durch ein Enter im Textfeld oder durch einen Klick auf einen Button abgeschickt hat, muss man ein paar Vorbereitungen treffen.
Für das Formular legen wir eine Bean an, welche die Daten aufnimmt.
package de.wicketpraxis.web.blog.pages.questions.form.submit;
import java.io.Serializable;
public class FormBean implements Serializable
{
String _name;
public String getName()
{
return _name;
}
public void setName(String name)
{
_name = name;
}
}
Für unser Beispiel benötigen wir ein Formular, einen AjaxFallbackButton, einen normalen Button und einen Button, den wir dazu benutzen, denn Fall herauszubekommen, wenn der Nutzer einfach nur Enter gedrückt hat. Das FeedbackPanel sollte man auch nicht vergessen.
package de.wicketpraxis.web.blog.pages.questions.form.submit;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.markup.html.form.AjaxFallbackButton;
import org.apache.wicket.markup.html.WebPage;
import org.apache.wicket.markup.html.form.Button;
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 FormSubmitPage extends WebPage
{
int _counter;
public FormSubmitPage()
{
final FeedbackPanel feedbackPanel = new FeedbackPanel("feedback");
feedbackPanel.setOutputMarkupId(true);
add(feedbackPanel);
CompoundPropertyModel<FormBean> formModel = new CompoundPropertyModel<FormBean>(new FormBean());
Form<FormBean> form = new Form<FormBean>("form",formModel)
{
@Override
protected void onSubmit()
{
info("Form Submit: "+_counter++);
}
};
form.add(new TextField<String>("name"));
form.add(new Button("defaultSubmit")
{
@Override
public void onSubmit()
{
info("Default Button: "+_counter++);
}
});
form.add(new Button("submit")
{
@Override
public void onSubmit()
{
info("Button: "+_counter++);
}
});
form.add(new AjaxFallbackButton("ajaxSubmit",form)
{
@Override
protected void onSubmit(AjaxRequestTarget target, Form<?> form)
{
if (target!=null)
{
info("AjaxSubmit Button(ajax): "+_counter++);
target.addComponent(feedbackPanel);
_counter=0;
}
else
{
info("AjaxFallbackButton: "+_counter++);
}
}
});
add(form);
}
@Override
protected void onBeforeRender()
{
_counter=0;
super.onBeforeRender();
}
}
Damit man die Reihenfolge besser erkennen kann, mit der die onSubmit-Methoden aufgerufen werden, wird ein Zähler (_counter) hochgezählt und vor dem Darstellen des Formulars wieder zurückgesetzt. In diesem Beispiel liegt die entscheidende Information im Markup. Dabei ist die Reihenfolge der verschiedenen Submit-Komponenten wichtig.
<html>
<head>
<title>FormSubmitPage</title>
</head>
<body>
<div wicket:id="feedback"></div>
<form wicket:id="form">
<input wicket:id="defaultSubmit" type="submit" value="" style="border:0px; width: 0px; height: 0px; visibility: collapse; display: compact;">
Name <input wicket:id="name"><br>
<input wicket:id="ajaxSubmit" type="submit" value="AjaxButton">
<input wicket:id="submit" type="submit" value="Button">
</form>
</body>
</html>
Der Button mit der Wicket-ID defaultSubmit muss vor allen anderen Submit-Komponenten stehen. Dadurch wird beim Abschicken des Formulars durch Enter dieser Button ausgewählt. Wenn einer der anderen Buttons angeklickt wird, dann wird das Formular über diesen Button abgeschickt. Doch warum soviel Aufwand? Die onSubmit()-Methode des Formulars wird doch in jedem Fall aufgerufen.
Der Aufwand ist notwendig, wenn man abhängig davon, ob der Nutzer auf einen Button oder eben auf keinen Button geklickt hat, eine Aktion ausführen möchte. Das bedeutet, dass man die Aktion nicht in onSubmit ausführen kann. Es ist allerdings auch nicht möglich, im onSubmit() der Buttonkomponenten ein Flag zu setzen, dass dann in der onSubmit()-Methode des Formulars aufgerufen wird, da die Methode beim AjaxFallbackButton erst nach dem onSubmit() der Komponente aufgerufen wird.
Folgende Ergebnisse erhält man, wenn man das Formular a) per Enter, b) per AjaxButton und c) per Button abschickt:
Wenn Javascript deaktiviert ist, dann erhält man folgende Ausgabe:
Wenn man dieses Vorgehen beherzigt, funktioniert die Anwendung auch mit deaktiviertem JavaScript genauso zuverlässig. Das freut den Nutzer und in diesem Fall auch den Entwickler:)