如何在JSF的selectOneMenu中添加“未选择”选项的最佳方法

45

我想知道在selectOneMenu中允许用户不选择任何内容的最佳或最简单的方法是什么。

我的例子:我有一个已注册用户列表,管理员应该能够通过一些条件筛选显示的用户列表。这些条件,如用户类型(员工、客户等),可以通过selectOneMenus选择,例如:

<h:selectOneMenu value="#{myBean.selectedUsertype}" converter="#{usertypeConverter}">
<f:selectItems value={myBean.usertypes}" />
</h:selectOneMenu>

当相应的selectOneMenu使用转换器由POJO列表支持时,如何向列表中添加一项,以指示用户没有选择任何特定项?目前,我有一个虚拟的用户类型对象显示标签“---”,但这会在我的应用程序的其他区域引起几个问题,我认为这不是最好的解决方案。

3个回答

105

只需将选择项目的值明确设置为 null

<h:selectOneMenu value="#{bean.selectedItem}">
    <f:selectItem itemValue="#{null}" itemLabel="--select--" />
    <f:selectItems value="#{bean.availableItems}" />
</h:selectOneMenu>

不,像itemValue=""这样的空字符串是不够的。它真正必须是null。否则,您会遇到问题,如此Q&A中所述:在p:selectOneMenu中使用具有null/empty值的"Please select" f:selectItem

如果该项恰好为required="true"并且您正在使用JSF 2.x,则可以将noSelectionOption="true"添加到选择项中。仅当您还将hideNoSelectionOption="true"设置为选择组件时,才有用。然后,一旦最终用户选择了不同的项目,它将隐藏列表中的空选项,从而使重新选择空选项成为不可能。

<h:selectOneMenu value="#{bean.selectedItem}" hideNoSelectionOption="true">
    <f:selectItem itemValue="#{null}" itemLabel="--select--" noSelectionOption="true" />
    <f:selectItems value="#{bean.availableItems}" />
</h:selectOneMenu>

请参见 JSF权威指南 第114页 "SelectItem标签" 章节。
请注意,值为#{null}的选择项可用于在与选择组件的value属性关联的bean属性为null的情况下呈现默认选择。如果您已经查阅了<f:selectItem>标记文档,则可能已经注意到noSelectionOption属性,并认为它旨在表示“无选择选项”。实际上,这并不是真的。许多初学者确实这样认为,正如您可以在许多论坛,问答网站和互联网上质量差的教程中看到的那样。尽管有误导性的属性名称,但它并不代表“无选择选项”。
更好的属性名称应该是hideWhenOtherOptionIsSelected,即使在父选择组件明确设置了hideNoSelectionOption =“true”属性时才起作用。因此,hideWhenOtherOptionIsSelectedAndHideNoSelectionOptionIsTrue最终将是最自我解释的属性名称。不幸的是,在JSF 1.2中实现noSelectionOption时没有考虑得很好。需要两个属性才能使此属性正常工作是不必要的。这对属性对的主要目的是防止网站用户在组件已经选择了非null值时重新选择“无选择选项”。例如,通过在@PostConstruct方法中准备它,或者通过在提交具有非null值的表单后重新呈现组件来实现。

版权声明:本书由我编写。


http://docs.oracle.com/cd/E17802_01/j2ee/j2ee/javaserverfaces/1.1_01/docs/api/index.html表示如果值为null,则应抛出NullPointerException。 - bruno
5
@bruno,那份文档是针对发布于10年前的JSF 1.1版本的。请更新你的书签。 - DavidS
@BalusC,它与转换器不兼容 - 它抛出空指针异常(JSF 2.2)。 - guest
@guest:那只是该转换器中的一个错误。如果您不知道如何修复它或找不到回答如何创建正确转换器的问题,请按“提问”按钮。 - BalusC
@BalusC,当items列表的类型为对象时,itemValue="#{null}"或itemValue="null"可以正常工作。那么如果items列表的值是int类型呢?在验证时,对于选定的值会抛出java.lang.IllegalArgumentException异常。 - Parkash Kumar
hideNoSelectionOption属性适用于primefaces <p:selectOneMenu>吗? - user2918640

10

添加一个值为null的单个selectItem

<h:selectOneMenu value="#{bean.question}" required="true" requiredMessage="Please select a question">
    <f:selectItem itemValue="#{null}" itemLabel="Select" />
    <f:selectItems value="#{bean.questions}" />
</h:selectOneMenu>

3
我们可以在primefaces中(当我们必须使用<p:selectOneMenu时,例如使用<p:ajax...)添加以下空白项:
<f:selectItem itemValue="#{null}" itemLabel="--select--"  itemDisabled="#{Mybean.value ne null}" />

注意:在这种情况下,我们不需要以下两个标签:
hideNoSelectionOption="true"

并且。
noSelectionOption="true"

你可以使用这个解决方案 @user2918640 - A. Qaoud
@Kukeltje:在选择其他值后,“select”标签将保留在菜单上。但在我的解决方案中,选择任何其他选项后,“select”标签将被禁用... - A. Qaoud
此帖子未添加任何新内容到已给出的答案中。如果您同意某个答案,请直接为其投票,而非重复发表相同的内容。Stack Overflow不像旧式讨论论坛那样,大家互相重复,导致信息难以消化。 - BalusC
@BalusC:如果您使用的是<p:selectOneMenu而不是<h:selectOneMenu,那么hideNoSelectionOption="true"和noSelectionOption="true"属性将不起作用,这正是user2918640在评论中询问您解决方案的原因。我本来想在他之后留下评论的,但由于我是stackoverflow的新手,没有足够的声望来这样做。所以,我认为把它作为解决方案发布是一个好主意。我并不是想重复您的话,并引起“难以消化的混乱”,正如您所说的那样。最后,非常感谢您的帖子,因为您在JSF方面提供了很多帮助... - A. Qaoud

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接