我想使用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>
答案 0 :(得分:3)
您的具体问题是由于您将多个组件物理绑定到同一个变量而引起的。
<h:selectOneMenu ... binding="#{cc.type}" />
<h:selectOneMenu ... binding="#{cc.type}" />
如果binding
后面的getter返回非null
,那么JSF将使用它而不是创建一个新的。基本上,第二个标记将重用第一个标记中创建的组件,并为其设置/添加所有属性/项。
您的具体案例至少可以通过两种方式解决:
使用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>
制作代码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>
答案 1 :(得分:0)
猜猜我发现了 - 但回答我的问题有点奇怪。我认为这是因为菜单的可能值是在评估渲染属性之前创建的,因为我将两个菜单绑定到相同的变量/ id,我得到了两个菜单中的所有项目。因此,我现在使用不同的名称,然后在我的复合组件中有一些逻辑,检查使用哪一个并继续使用正确的值。作品: - )
对我来说有点奇怪的是,作为开发人员,你必须知道何时构建属性列表与渲染发生时相比。我最近有一个类似的foreach和重复问题。有没有办法知道这些事情是我能记住的一些总体概念的一部分,还是真的是个案? 谢谢你们!