选择菜单的动态数量

dynamic number of selectonemenu

我有两段代码,一段有效,一段无效。我正在从不同 selectOneMenu 的列表中访问不同的对象。因此,如果我的列表大小为 4,那么我有 4 selectOneMenuselectOneMenu 上面有一个 spinner 来通知我想要多少个。 我不明白为什么第一个使用 varstatus 访问列表有效,而第二个使用 var 的无效。 Map 是一个自定义实体 btw。

有效:

<p:spinner value="#{matchCreation.numbreOfmaps}" min="1" max="7">
    <f:ajax event="change" render="mapsGroup" execute="mapsGroup"/>
</p:spinner>
<!-- maps start  -->
<h:panelGroup id="mapsGroup">
    <table>
        <ui:repeat var="mapPlayed" value="#{matchCreation.playedMaps}" varStatus="status">
            <tr><td>
                <p:selectOneMenu value="#{matchCreation.playedMaps[status.index]}">
                    <f:selectItems value="#{matchCreation.mapList}" var="map" itemValue="#{map}" itemLabel="#{map.name}"/>
                    <f:converter binding="#{mapConverter}"/>
                </p:selectOneMenu>
            </td></tr>  
        </ui:repeat> 
    </table>
</h:panelGroup>

不起作用:

<p:spinner value="#{matchCreation.numbreOfmaps}" min="1" max="7">
    <f:ajax event="change" render="mapsGroup" execute="mapsGroup"/>
</p:spinner>
<!-- maps start  -->
<h:panelGroup id="mapsGroup">
    <table>
        <ui:repeat var="mapPlayed" value="#{matchCreation.playedMaps}">
            <tr><td>
                <p:selectOneMenu value="#{mapPlayed}">
                    <f:selectItems value="#{matchCreation.mapList}" var="map" itemValue="#{map}" itemLabel="#{map.name}"/>
                    <f:converter binding="#{mapConverter}"/>
                </p:selectOneMenu>
            </td></tr>  
        </ui:repeat> 
    </table>
</h:panelGroup>

在此列表中,列表将包含指定的地图数量,但它们都将等于 mapList.get(0)

java:

private List<Map> mapList; // initiated in post construct.
private List<Map> playedMaps;
private int numbreOfmaps = 1;

public List<Map> getPlayedMaps() {
    // I know this is not advised but I didn't really think of another way.
    // It's not heavy work anyway.
    while (playedMaps.size() > numbreOfmaps) {
        playedMaps.remove(playedMaps.size() - 1);
    }
    while (playedMaps.size() < numbreOfmaps) {
        playedMaps.add(mapList.get(0));
    }
    return playedMaps;
}

<ui:repeat var="mapPlayed"> 表示作用域变量,而不是 bean 属性。想象一下 "under the covers" 的工作原理,它看起来像:

for (Map mapPlayed : matchCreation.getPlayedMaps()) {
    // ...
    System.out.println(mapPlayed);
}

当使用 <p:selectOneMenu value="#{mapPlayed}"> 时,JSF 实际上在作用域变量中设置提交的值,而不是 bean 属性。在幕后,想象一下:

for (Map mapPlayed : matchCreation.getPlayedMaps()) {
    Map newMapPlayed = getSubmittedValueSomehow();
    mapPlayed = newMapPlayed;
    // ...
}

这没有反映在列表中。

使用循环索引效果更好:

for (int index = 0; index < matchCreation.getPlayedMaps().size(); index++) 
    Map newMapPlayed = getSubmittedValueSomehow();
    matchCreation.getPlayedMaps().set(index, newMapPlayed);
    // ...
}

与具体问题无关,隐藏标准 Java SE API 类 的名称,如 Map(来自 java.util.Map) 是一个非常糟糕的主意。