如何使用SelectManyCheckbox和ArrayList作为HashMap值

问题描述 投票:0回答:1

我正在尝试将 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));
    }
    
}

D到

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;
    }
}

Xhtml

<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()}" />
jsf primefaces mojarra
1个回答
0
投票

你是泛型类型擦除的受害者。

基本上,在原始 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 修复了此问题。

© www.soinside.com 2019 - 2024. All rights reserved.