[英]Wicket table with variable number of columns
我一直在通過向頁面添加ListView
(將我的數據作為List<MyObject>
)創建表,並將相應的id分配給html文件中的每一列。
但是現在我有一種情況,而不是簡單的List<MyObject>
我有List<Map<String,MyObject>>
。 我還得到一個列表,其中包含嵌套映射的所有可能鍵( List<String>
)。 現在我需要創建一個表,其中Map
每個值都應該在列中,並且鍵的名稱指向該值。
假設我有以下數據:
keys = ['a', 'b']
data = [ { 'a' = 1, 'b' = 2 },
{ 'a' = 3, 'b' = 4 },
{ 'a' = 5, 'b' = 6}]
我想創建表:
<table>
<tr>
<th>a</th>
<th>b</th>
</tr>
<tr>
<td>1</td>
<td>2</td>
</tr>
<tr>
<td>3</td>
<td>4</td>
</tr>
<tr>
<td>5</td>
<td>6</td>
</tr>
</table>
知道嵌套Map中的鍵的名稱和數量可以改變,在wicket中實現它的最佳方法是什么?
下面是使用DefaultDataTable和嵌套ListViews的示例。
請注意,雖然DataTable方法可能看起來不那么簡單(好吧,它取決於旁觀者的眼睛),但它實際上將更清晰的數據提取與可視化分離,並且您可以開箱即用分頁:嘗試添加更多數據,或者降低rowsPerPage
(DefaultDataTable的最后一個構造函數參數)。
public class HomePage extends WebPage {
static final String A = "a";
static final String B = "b";
public HomePage() {
final List<String> keys = Arrays.asList(A, B);
final List<Map<String, Integer>> data = Arrays.asList(
map(A, 1).put(B, 11).toMap(),
map(A, 2).put(B, 12).toMap(),
map(A, 3).put(B, 13).toMap(),
map(A, 4).put(B, 14).toMap(),
map(A, 5).put(B, 15).toMap(),
map(A, 6).put(B, 16).toMap(),
map(A, 7).put(B, 17).toMap(),
map(A, 8).put(B, 18).toMap(),
map(A, 9).put(B, 19).toMap());
// Using a DefaultDataTable
ISortableDataProvider dataProvider = new SortableDataProvider() {
public Iterator iterator(int first, int count) {
int start = Math.min(0, first);
int end = Math.min(data.size(), start + count);
return data.subList(start, end).iterator();
}
public int size() {
return data.size();
}
public IModel model(Object object) {
return new CompoundPropertyModel(object);
}
};
List columns = new ArrayList();
for (String key : keys)
columns.add(new PropertyColumn(Model.of(key), key));
add(new DefaultDataTable("dataTable", columns, dataProvider, 20));
// Using a nested ListViews
add(new ListView("headers", keys) {
@Override
protected void populateItem(ListItem item) {
item.add(new Label("header", String.valueOf(item.getModelObject())));
}
});
add(new ListView("listView", data) {
@Override
protected void populateItem(ListItem item) {
final Map rowMap = (Map) item.getModelObject();
item.add(new ListView("nested", keys) {
@Override
protected void populateItem(ListItem item) {
Object value = rowMap.get(item.getModelObject());
item.add(new Label("value", String.valueOf(value)));
}
});
}
});
}
// to make building the data structure a little more fun :)
private MapBuilder<String, Integer> map(String key, Integer value) {
return new MapBuilder<String, Integer>().put(key, value);
}
private static class MapBuilder<K, V> {
Map<K, V> map = new HashMap<K, V>();
MapBuilder<K, V> put(K key, V value) {
map.put(key, value);
return this;
}
Map<K, V> toMap() {
return map;
}
}
}
<html xmlns:wicket="http://wicket.apache.org">
<body>
<table wicket:id="dataTable"></table>
<table>
<tr>
<th wicket:id="headers">
<span wicket:id="header"></span>
</th>
</tr>
<tr wicket:id="listView">
<td wicket:id="nested">
<span wicket:id="value"></span>
</td>
</tr>
</table>
</body>
</html>
您可以嵌套ListView
。 你想要的標記看起來像這樣:
<table>
<tr><th wicket:id="headerlist"><span wicket:id="header"></span></th></tr>
<tr wicket:id="contentlist"><td wicket:id="column">
<span wicket:id="data"></span>
</td></tr>
</table>
然后,您將需要三個ListView
。 第一個( headerlist
)將填充keys
列表中的標題。 這很簡單,所以我將跳過這個例子。
第二( contentlist
)將在您的data
列表。 在populateItems
方法中,您將添加第三個ListView
( column
),它將再次遍歷keys
列表:
add(new ListView<Map<String,MyObject>>("contentlist", data) {
protected void populateItem(ListItem<Map<String,MyObject>> item) {
final Map<String,MyObject> map = item.getModelObject();
// Inner list - using item.add to add to the inner list
item.add(new ListView<String>("column", keys) {
protected void populateItem(ListItem<String> item) {
String key = item.getModelObject();
item.add(new Label("data", map.get(key).toString()));
}
});
}
});
您當然可以使用嵌套的ListView
,但您也可以使用專門為此任務設計的DataTable
及其后代。 作為獎勵,您還可以從中獲取分類和分頁等內容。
謝謝Tetsuo! 我已經為Tetsuo的變量列示例填寫了Generics:
Wicket HTML
<html xmlns:wicket="http://wicket.apache.org">
<body>
<h3>Example 1</h3>
<table wicket:id="dataTable"></table>
<br>
<h3>Example 2</h3>
<table>
<tr>
<th wicket:id="headers">
<span wicket:id="header"></span>
</th>
</tr>
<tr wicket:id="listView">
<td wicket:id="nested">
<span wicket:id="value"></span>
</td>
</tr>
</table>
</body>
</html>
Wicket Java
public class HomePage extends WebPage
{
/** Represents serialVersionUID. */
private static final long serialVersionUID = 20150701L;
static final String A = "alpha";
static final String B = "beta";
static final String C = "gamma";
public HomePage()
{
super();
final List<String> keys = Arrays.asList(A, B, C);
final List<Map<String,Integer>> data = Arrays.asList
(
map(A, 1).put(B, 11).put(C, 21).toMap(),
map(A, 2).put(B, 12).put(C, 22).toMap(),
map(A, 3).put(B, 13).put(C, 23).toMap(),
map(A, 4).put(B, 14).put(C, 24).toMap(),
map(A, 5).put(B, 15).put(C, 25).toMap(),
map(A, 6).put(B, 16).put(C, 26).toMap(),
map(A, 7).put(B, 17).put(C, 27).toMap(),
map(A, 8).put(B, 18).put(C, 28).toMap(),
map(A, 9).put(B, 19).put(C, 29).toMap()
);
// Using a DefaultDataTable
ISortableDataProvider<Map<String,Integer>,String> dataProvider =
new SortableDataProvider<Map<String,Integer>,String>()
{
/** Represents serialVersionUID. */
private static final long serialVersionUID = HomePage.serialVersionUID;
public Iterator<Map<String,Integer>> iterator(long first, long count)
{
int start = Math.max(0, (int) first);
int end = Math.min(data.size(), start + (int) count);
return data.subList(start, end).iterator();
}
public long size()
{
return data.size();
}
public IModel<Map<String,Integer>> model(Map<String,Integer> object)
{
return new CompoundPropertyModel<Map<String,Integer>>(object);
}
};
List<PropertyColumn<Map<String,Integer>,String>> columns =
new ArrayList<PropertyColumn<Map<String,Integer>,String>>();
for (String key : keys)
columns.add(new PropertyColumn<Map<String,Integer>,String>(Model.of(key), key));
// Example 1 - Using a DataTable
// Wicket: "dataTable"
add(new DefaultDataTable<Map<String,Integer>,String>("dataTable", columns, dataProvider, 5));
// Example 2 - Using nested ListViews
// Wicket: "headers"
add
(
new ListView<String>("headers", keys)
{
/** Represents serialVersionUID. */
private static final long serialVersionUID = HomePage.serialVersionUID;
@Override
protected void populateItem(ListItem<String> item)
{
// Wicket: "header"
item.add(new Label("header", String.valueOf(item.getModelObject())));
}
}
);
add
(
// Wicket: "listView"
new ListView<Map<String,Integer>>("listView", data)
{
/** Represents serialVersionUID. */
private static final long serialVersionUID = HomePage.serialVersionUID;
@Override
protected void populateItem(ListItem<Map<String,Integer>> item)
{
final Map<String,Integer> rowMap = item.getModelObject();
item.add
(
// Wicket: "nested"
new ListView<String>("nested", keys)
{
private static final long serialVersionUID = HomePage.serialVersionUID;
@Override
protected void populateItem(ListItem<String> item)
{
Integer value = rowMap.get(item.getModelObject());
// Wicket: "value"
item.add(new Label("value", String.valueOf(value)));
}
}
);
}
}
);
}
// Make building the data structure a little more fun :)
private MapBuilder<String, Integer> map(String key, Integer value)
{
return new MapBuilder<String, Integer>().put(key, value);
}
private static class MapBuilder<K, V>
{
Map<K, V> map = new HashMap<K, V>();
MapBuilder<K, V> put(K key, V value)
{
map.put(key, value);
return this;
}
Map<K, V> toMap()
{
return map;
}
}
}
通用用法
DefaultDataTable擴展了DataTable
IColumn
ISortableDataProvider
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.