<h:selectonemenu with =“”conditional =“”<f:selectitems =“”shows =“”options =“”two =“”

时间:2016-08-08 18:29:42

标签: jsf jsf-2.2

=“”

我想使用selectOneMenu让用户选择一个值。在某些情况下,我想禁用菜单中显示的其中一个值。我尝试在selectItems和selectOneMenu上使用render,并在菜单周围添加了一个ui:fragment,但我总是得到两个列表中显示的所有值。任何想法如何预防? 在这里,我当前的最后一次尝试再次导致列表的两倍,并且一旦启用并且在其中禁用了该项目:

<ui:fragment rendered="#{cc.attrs.showP==true}">
    <h:selectOneMenu id="type" binding="#{cc.type}">
        <f:selectItems value="#{typeDAO.findAll()}"/>
    </h:selectOneMenu>
</ui:fragment>
<ui:fragment rendered="#{cc.attrs.showP==false}">
    <h:selectOneMenu id="type" binding="#{cc.type}">
        <f:selectItems value="#{typeDAO.findAll()}" var="item" itemDisabled="#{item=='P'}"/>
    </h:selectOneMenu>
</ui:fragment>

2 个答案:

答案 0 :(得分:3)

您的具体问题是由于您将多个组件物理绑定到同一个变量而引起的。

<h:selectOneMenu ... binding="#{cc.type}" />
<h:selectOneMenu ... binding="#{cc.type}" />

如果binding后面的getter返回非null,那么JSF将使用它而不是创建一个新的。基本上,第二个标记将重用第一个标记中创建的组件,并为其设置/添加所有属性/项。

您的具体案例至少可以通过两种方式解决:

  1. 使用JSTL有条件地构建JSF组件树,而不是使用JSF有条件地呈现HTML输出。您不应该在JSF组件树中拥有物理上多个组件,共享相同的binding,更不用说相同的id

    <c:if test="#{cc.attrs.showP}">
        <h:selectOneMenu id="type" binding="#{cc.type}">
            ...
        </h:selectOneMenu>
    </c:if>
    <c:if test="#{not cc.attrs.showP}">
        <h:selectOneMenu id="type" binding="#{cc.type}">
            ...
        </h:selectOneMenu>
    </c:if>
    
  2. 制作代码DRY。即摆脱所有代码重复。

    <h:selectOneMenu id="type" binding="#{cc.type}">
        <f:selectItems value="#{typeDAO.findAll()}" var="item" itemDisabled="#{not cc.attrs.showP and item eq 'P'}" />
    </h:selectOneMenu>
    
  3. 另见:

答案 1 :(得分:0)

猜猜我发现了 - 但回答我的问题有点奇怪。我认为这是因为菜单的可能值是在评估渲染属性之前创建的,因为我将两个菜单绑定到相同的变量/ id,我得到了两个菜单中的所有项目。因此,我现在使用不同的名称,然后在我的复合组件中有一些逻辑,检查使用哪一个并继续使用正确的值。作品: - )

对我来说有点奇怪的是,作为开发人员,你必须知道何时构建属性列表与渲染发生时相比。我最近有一个类似的foreach和重复问题。有没有办法知道这些事情是我能记住的一些总体概念的一部分,还是真的是个案? 谢谢你们!