java 列数可变的检票表
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5500308/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Wicket table with variable number of columns
提问by Mario Duarte
I've been creating tables by adding a ListView
(providing it with my data as a List<MyObject>
) to the page, and assigning the corresponding ids to each column in the html file.
我一直在通过向页面添加 a ListView
(将我的数据作为 a 提供给它List<MyObject>
)来创建表格,并将相应的 id 分配给 html 文件中的每一列。
However now I have a situation where instead of a simple List<MyObject>
I have List<Map<String,MyObject>>
. I also get a list with all the possible keys of the nested map (List<String>
). Now I need to create a table where each value of the Map
should be in the column with the name of the key pointing to that value.
但是现在我有一个情况,而不是一个简单的List<MyObject>
我有List<Map<String,MyObject>>
. 我还得到了一个包含嵌套映射 ( List<String>
) 的所有可能键的列表。现在我需要创建一个表,其中的每个值都Map
应该在键名指向该值的列中。
Let's say I have the following data:
假设我有以下数据:
keys = ['a', 'b']
data = [ { 'a' = 1, 'b' = 2 },
{ 'a' = 3, 'b' = 4 },
{ 'a' = 5, 'b' = 6}]
I would like to create the table:
我想创建表:
<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>
Knowing that the names and number of keys in the nested Map can change, what is the best way to implement this in wicket?
知道嵌套 Map 中键的名称和数量可以更改,在 wicket 中实现这一点的最佳方法是什么?
回答by tetsuo
Below, examples using DefaultDataTable and nested ListViews.
下面是使用 DefaultDataTable 和嵌套 ListViews 的示例。
Note that, while the DataTable approach may look less straightforward (well, it depends on the eye of the beholder), it actually separates more cleanly data fetching from visualization, and you get pagination out-of-the-box: try adding more data, or lowering the rowsPerPage
(DefaultDataTable's last constructor param).
请注意,虽然 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>
回答by Adrian Cox
You can nest ListView
. The markup you want will look something like this:
你可以嵌套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>
You will then need three ListView
. The first (headerlist
) will fill in the headers from the keys
list. This is simple, so I'll skip the example.
然后你需要三个ListView
。第一个 ( headerlist
) 将填充keys
列表中的标题。这很简单,所以我将跳过这个例子。
The second (contentlist
) will be across your data
list. In the populateItems
method you will add the third ListView
(column
), which will again iterate across the keys
list:
第二个 ( 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()));
}
});
}
});
回答by biziclop
回答by Rick O'Sullivan
Thanks Tetsuo! I've filled in the Generics for Tetsuo's variable column examples:
谢谢哲雄!我已经为 Tetsuo 的变量列示例填写了泛型:
- DefaultDataTable
- Nested ListViews
- 默认数据表
- 嵌套列表视图
Wicket HTML
检票口 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;
}
}
}
Generic Usage
通用用法
DefaultDataTable extends DataTable
DefaultDataTable 扩展了 DataTable
- @param The model object type
- @param The type of the sorting parameter
- @param 模型对象类型
- @param 排序参数的类型
IColumn
专栏
- @param The type of the object that will be rendered in this column's cells
- @param The type of the sorting parameter
- @param 将在此列的单元格中呈现的对象的类型
- @param 排序参数的类型
ISortableDataProvider
ISortableDataProvider
- @param The model object type (omitted in JavaDoc) ??
- @param The type of the sorting parameter
- @param 模型对象类型(JavaDoc 中省略) ??
- @param 排序参数的类型