我想使用selectOneMenu让用户选择一个值。在某些情况下,我想禁用菜单中显示的一个值。我试着在selectems和selectOneMenu上使用渲染,并在菜单周围添加了一个ui:片段,但我总是从两个列表中得到所有的值。有什么办法可以防止吗?在这里,我当前的最后一次尝试再次导致两次列表和有问题的项目一次启用,一次禁用:
<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>
你的具体问题是因为你将多个组件物理地绑定到同一个变量。
<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>
参见:
- 如何'绑定'属性在JSF中工作吗?何时以及如何使用?
- JSTL在JSF2 Facelets…有道理吗?
我猜我觉得回答我的问题有点奇怪。我认为这是因为菜单的可能值是在评估呈现属性之前创建的,并且因为我确实将两个菜单绑定到相同的变量/id,所以我得到了两个菜单的所有项。因此,我现在使用了不同的名称,然后在我的组合组件中使用一些逻辑来检查使用了哪个名称并继续使用正确的值。: -)
对我来说有点奇怪的是,作为一名开发人员,你必须知道属性列表何时构建,以及渲染何时发生。我最近也遇到了类似的问题。有没有什么方法可以把这些东西作为我能记住的总体概念的一部分或者是具体情况具体分析?谢谢你们了!