Ich wurde gefragt, ob in meinem Buch (Praxisbuch Wicket) die Verwendung der CheckGroup-Komponente erläutert wird. Die Anwort ist einfach: ja.
Was in dem Beispiel aber nicht gezeigt wird, ist das dynamische Erzeugen der Auswahlliste durch Daten aus einer Datenbank. Der Absender hat sich aber genau für diesen Fall interessiert, so dass ich an dieser Stelle mal ein einfaches Beispiel geben möchte, wie man soetwas realisieren kann.
Das Beispiel
package de.wicketpraxis.web.blog.pages.questions.checkgroup.fromdb;
import java.util.ArrayList;
import java.util.List;
import org.apache.wicket.markup.html.WebPage;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.Check;
import org.apache.wicket.markup.html.form.CheckGroup;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.list.ListItem;
import org.apache.wicket.markup.html.list.ListView;
import org.apache.wicket.markup.html.panel.FeedbackPanel;
import org.apache.wicket.model.LoadableDetachableModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.model.util.CollectionModel;
import org.apache.wicket.spring.injection.annot.SpringBean;
import de.wicketpraxis.persistence.beans.User;
import de.wicketpraxis.persistence.dao.UserDao;
public class CheckGroupFromDbPage extends WebPage
{
@SpringBean
UserDao _userDao;
public CheckGroupFromDbPage()
{
LoadableDetachableModel<List<User>> userListModel=new LoadableDetachableModel<List<User>>()
{
@Override
protected List<User> load()
{
return _userDao.findAll(0, 10);
}
};
final IModel<Collection<Integer>> selectedModel = new CollectionModel<Integer>(new ArrayList<Integer>());
add(new FeedbackPanel("feedback"));
Form<Void> form=new Form<Void>("form")
{
@Override
protected void onSubmit()
{
info("Elemente selectiert: "+selectedModel.getObject());
}
};
CheckGroup<Integer> checkGroup=new CheckGroup<Integer>("checkGroup",selectedModel);
form.add(checkGroup);
checkGroup.add(new ListView<User>("list",userListModel)
{
@Override
protected void populateItem(ListItem<User> item)
{
item.add(new Check<Integer>("check",Model.of(item.getModelObject().getId())));
item.add(new Label("name",item.getModelObject().getName()));
}
});
add(form);
}
}
Und das Markup-File:
<html>
<head>
<title>CheckGroup from DB</title>
</head>
<body>
<div wicket:id="feedback"></div>
<form wicket:id="form">
<wicket:container wicket:id="checkGroup">
<wicket:container wicket:id="list">
<input wicket:id="check" type="checkbox"> <span wicket:id="name"></span><br>
</wicket:container>
</wicket:container>
<input type="submit" value="Auswählen">
</form>
</body>
</html>
Die Variable _userDao beinhaltet die Datenbankzugriffsklasse. Da wir die Variable als Field definiert haben, können wir ohne weiteres innerhalb der Klasse darauf zugreifen. Wicket sorgt für alle über die SpringBean-Annotation initialisierten Felder dafür, dass es mit der Serialisierung der Komponente keine Probleme gibt.
Als nächstes erstellen wir ein Modell, dass die gewünschte Auswahlmenge ermittelt. An dieser Stelle könnte man über ein CascadingLoadableDetachableModel (kein Wicket-Standard, siehe Buch Seite 65 oder hier im Blog) auch auf die Modelldaten eines Eingabefeldes zurückgreifen um die Abfrage einsprechende zu beeinflussen zu können. Das Ergebis ist eine Liste von Objekten.
Als zweiter erstellen wir ein Modell, in dem die IDs der ausgewählten Elemente landen. Um den Aufwand einer eigenen Implementierung einer Modellklasse für eine Collection von persistenten Objekten zu sparen, legen wir nur die ID des Elements, nicht das Element selbst in der Auswahlliste ab.
Das Feedbackpanel dient zur Anzeige die Message, die in der onSubmit-Methode des Formulars ausgegeben wird. Das Formular hat in diesem Fall kein eigenes Modell (nur der Einfachheit halber wird in dem Beispiel auf die Verwendung eines CompoundPropertyModel verzichtet).
Jetzt kommt der spannende Teil. Der CheckGroup-Komponente wird als Parameter das Modell übergeben, in der die Ausgewählten Elemente gesammelt werden sollen. Dann wird in der ListView für alle zur Verfügung stehenden Elemente eine Check-Komponente hinzugefügt, die als Modell nicht das Objekt, sondern die ID des Datenbankeintrags übergeben bekommt.
Funktionsweise
Wenn das Formular abgeschickt wird, ermittelt Wicket alle Check-Komponenten, die aktiviert waren. Für diese Komponenten wird der Inhalt des Modells ermittelt und der Auswahlliste hinzugefügt. Abschließend wird das Modell, dass die Auswahlliste beinhaltet entsprechend gesetzt. Dabei können beliebige Typen für die Auswahlliste benutzt werden, solange sie serialisierbar sind. Kommen die Daten aus einer Datenbank empfiehlt sich der Einsatz eines Primärschlüssels, anhand dessen das Objekt ermittelbar bleibt.