问题
Using JSF 2.1 with primefaces
class FOO{
String name;
String value;
public void setName(String name){
this.name=name;
}
public String getName(){
return this.name;
}
public void setValue(String value){
this.value=value;
}
public String getValue(){
return this.value;
}
}
I have an Map<String, List<FOO>>
Header name should be Key of the Map. I need to create multiple columns (i.e. size of Map) and each column should have the list of FOO to display FOO.Name in rows.
For Example : if size of map is 4
Coulmns-----Key1
ROWs of 1st column - List<FOO>
against Key1
Coulmns-----Key2
ROWs of 1st column - List<FOO>
against Key2
Coulmns-----Key3
ROWs of 1st column - List<FOO>
against Key3
Coulmns-----Key4
ROWs of 1st column - List<FOO>
against Key4
Can someone tell me what component to use for displaying this type of output in xhtml page ? I have tried using dynamic datatable creation but not able to show this.
回答1:
You've there a wrong data structure. Change it to the right data structure. Easiest is to collect the data in a List<Map<String, Object>>
which represents the rows
property. The Map
represents the columns, keyed by a column name. Collect those column names in a separate List<String>
which represents the columns
property. Finally show it as follows by <p:columns>
:
<p:dataTable value="#{bean.rows}" var="row">
<p:columns value="#{bean.columns}" var="column">
#{row[column]}
</p:columns>
</p:dataTable>
Here's how you could convert the strange data structure to the right data structure, if necessary (and assuming that each List<FOO>
is of the same size; the whole data structure makes otherwise less sense):
Map<String, List<FOO>> wrongDataStructure = createItSomehow();
List<String> columns = new ArrayList<String>(wrongDataStructure.keySet()); // Note I expect LinkedHashMap ordering here.
List<Map<String, Object>> rows = new ArrayList<Map<String, Object>>();
int size = wrongDataStructure.values().iterator().next().size();
for (int i = 0; i < size; i++) {
Map<String, Object> row = new HashMap<String, Object>();
for (String column : columns) {
row.put(column, wrongDataStructure.get(column).get(i).getName());
}
rows.add(row);
}
// Now use "columns" and "rows".
回答2:
I couldn't figure out a way to do this without using a trick: Since the size of your lists in the map may differ for each key set, you need to know the size of the list with largest item set. By knowing that you can come up with this bizarre solution: The idea is to have a for loop in a for loop.
private Map<String, List<Foo>> fooMap = Maps.newHashMap();
private List<Foo> highestNumberOfFoos;
private init()
{
highestNumberOfFoos = Lists.newArrayList(new Foo("a", "b"), new Foo("c", "d"), new Foo("e", "f")); // We know that there won't be any list who has more items than this item.
fooMap.put("name1", highestNumberOfFoos);
fooMap.put("name2", Lists.newArrayList(new Foo("g", "h"), new Foo("i", "j")));
}
...and in the view:
<table>
<thead>
<tr>
<ui:repeat value="#{bean.fooMap.keySet().toArray()}" var="key">
<td>#{key}</td>
</ui:repeat>
</tr>
</thead>
<tbody>
<ui:repeat value="#{bean.highestNumberOfFoos}" var="dummyFoo" varStatus="vs">
<tr>
<ui:repeat value="#{bean.fooMap.entrySet().toArray()}" var="innerEntry">
<td>#{innerEntry.value[vs.index].name}</td>
</ui:repeat>
</tr>
</ui:repeat>
</tbody>
</table>
来源:https://stackoverflow.com/questions/14612034/how-to-iterate-mapstring-collection-in-datatable-in-primefaces