我正在尝试将 SelectManyCheckbox 的选定值绑定到 ArrayList,这是我的 HashMap 的值。
如果我的选项位于 ArrayList 内,并且选定的选项也是如此。我没有问题。
但是当我想将这些选定的选项设置为地图的值时。无论我尝试什么,它都会填充一个 Object[] 数组。
我正在使用 Mojarra 4.0.5。
@Component
@ViewScoped
@Getter
@Setter
public class TestView {
Map<String, ArrayList<Dto>> map;
ArrayList<String> strings;
ArrayList<Dto> options;
@PostConstruct
public void init() {
Dto dto1 = new Dto();
Dto dto2 = new Dto();
dto1.setAge(1);
dto1.setName("OPTION1");
dto2.setAge(2);
dto2.setName("OPTION2");
options = new ArrayList<Dto>();
options.add(dto1);
options.add(dto2);
map = new HashMap<String, ArrayList<Dto>>();
strings = new ArrayList<String>();
strings.add(new String("TEST1"));
strings.add(new String("TEST2"));
strings.forEach(s -> map.put(s, new ArrayList<Dto>()));
}
public void debug() {
System.out.println("debug");
ArrayList<ArrayList<Dto>> testarr = new ArrayList<ArrayList<Dto>>();
map.forEach((k,v)->testarr.add(v));
}
}
public class Dto {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
@FacesConverter(value="myConverter")
public class MyConverter implements Converter<Dto> {
private Map<Dto, String> entities = new HashMap<Dto, String>();
@Override
public String getAsString(FacesContext context, UIComponent component, Dto value) {
synchronized (entities) {
if (!entities.containsKey(value)) {
String uuid = UUID.randomUUID().toString();
entities.put(value, uuid);
return uuid;
} else {
return entities.get(value);
}
}
}
@Override
public Dto getAsObject(FacesContext context, UIComponent component, String value) {
for (Map.Entry<Dto, String> entry : entities.entrySet()) {
if (entry.getValue().equals(value)) {
return entry.getKey();
}
}
return null;
}
}
<ui:repeat var="str" value="#{testView.strings}" varStatus="strStatus">
<ui:param name="indexStr" value="#{strStatus.index}" />
<p:selectManyCheckbox value="#{testView.map[str]}"
converter="myConverter" layout="responsive" columns="6">
<p:ajax process="@this" />
<f:selectItems value="#{testView.options}" var="item"
itemLabel="#{item.name}" itemValue="#{item}" />
</p:selectManyCheckbox>
</ui:repeat>
<p:commandButton value="debug" icon="pi pi-check" process="@this"
action="#{testView.debug()}" />
你是泛型类型擦除的受害者。
基本上,在原始 Java 源代码中,您有
Map<String, ArrayList<Dto>> map
。
但是在该代码的编译输出中,它已变成
Map map
并且有关 String
和 ArrayList<Dto>
的信息丢失了。
这与 EL 表达式
#{...}
面临的问题相同。当它尝试检查 value="#{testView.map[str]}"
的类型时,它会检索 java.lang.Object
而不是 java.lang.ArrayList
。
从技术上来说,如下设置
collectionType
属性是必须的
<p:selectManyCheckbox ... collectionType="java.util.ArrayList">
但令我惊讶的是它确实没有任何效果。仅当
java.lang.Object
实际上是 java.util.Collection
的实例时,它才有效。我认为这是 Mojarra 中的一个错误。我已通过 issue 5427 修复了此问题。