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

Posted

技术标签:

【中文标题】在 JSF 中向 selectOneMenu 添加“未选择”选项的最佳方法【英文标题】:Best way to add a "nothing selected" option to a selectOneMenu in JSF 【发布时间】:2012-07-06 10:00:25 【问题描述】:

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

我的示例:我有一个注册用户列表,管理员应该能够按某些条件过滤显示的用户列表。这些标准,如用户类型(员工、客户、...)可以由 selectOneMenus 选择,如下所示:

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

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

【问题讨论】:

【参考方案1】:

只需将选择项的值显式设置为null

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

不,像itemValue="" 这样的空字符串是不够的。它真的必须是null。否则,您会遇到本问答中所述的麻烦:Using a "Please select" f:selectItem with null/empty value inside a p:selectOneMenu。

如果项目恰好是 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>

另请参阅The Definitive Guide to JSF 第 114 页的“SelectItem 标签”部分:

请注意,如果与选择组件的value 属性关联的bean 属性为null,则可以使用值为#null 的选择项来呈现默认选择。如果您查阅过&lt;f:selectItem&gt; 的标签文档,那么您可能已经注意到noSelectionOption 属性并认为它旨在表示“无选择选项”。事实上,这不是真的。许多初学者确实是这样认为的,正如您在互联网上的许多论坛、问答网站和劣质教程中看到的那样。尽管属性名称具有误导性,但它并不代表“无选择选项”。

更好的属性名称应该是hideWhenOtherOptionIsSelected,即使这样,它也只有在父选择组件明确设置了hideNoSelectionOption="true" 属性时才有效。因此,hideWhenOtherOptionIsSelectedAndHideNoSelectionOptionIsTrue 最终将是最不言自明的属性名称。不幸的是,当noSelectionOption 在JSF 1.2 中实现时,这并没有得到很好的考虑。不需要两个属性才能使该属性起作用。此属性对的主要目的是防止网站用户在组件已经选择了非null 值时能够重新选择“无选择选项”。例如,通过在 @PostConstruct 方法中准备它,或者通过在表单提交后使用非 null 值重新渲染组件。

版权声明:本书是我写的。

【讨论】:

docs.oracle.com/cd/E17802_01/j2ee/j2ee/javaserverfaces/1.1_01/… 表示当值为 null 时应该抛出 NullPointerException。 @bruno,该文档适用于 10 年前发布的 JSF 1.1。请更新您的书签。 @BalusC,它不适用于转换器 - 它会抛出 NullPointerException (JSF 2.2)。 @guest:这只是相关转换器中的一个错误。如果您不知道如何解决该问题或找不到回答如何创建合适转换器的问题,请按“”按钮。 @BalusC, itemValue="#null" 或 itemValue="null" 当项目列表是对象类型时工作正常。如果项目列表值是 int 类型怎么办?在验证的情况下,它会为选定的值抛出 java.lang.IllegalArgumentException。【参考方案2】:

添加一个具有空值的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 中(当我们必须使用 &lt;p:selectOneMenu... 时,出于某种原因,例如使用 &lt;p:ajax..)添加以下空项:

<f:selectItem itemValue="#null" itemLabel="--select--"  itemDisabled="#Mybean.value ne null" />

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

hideNoSelectionOption="true"

noSelectionOption="true"

【讨论】:

你可以使用这个解决方案@user2918640 @Kukeltje :选择另一个值后,“选择”标签将保留在菜单上。但在我的解决方案中,选择任何其他选项后,“选择”标签将被禁用...... 这篇文章并没有为已经给出的答案添加任何新内容。如果您同意某个答案,只需点赞即可,不要重复。 Stack Overflow 不像一个老式的讨论论坛,每个人都会互相重复,变成无法消化的混乱。 @BalusC : hideNoSelectionOption="true" 和 noSelectionOption="true" 属性在您使用

以上是关于在 JSF 中向 selectOneMenu 添加“未选择”选项的最佳方法的主要内容,如果未能解决你的问题,请参考以下文章

JSF 2.0:对 selectOneMenu 使用枚举值 [重复]

如何在 JSF 标记 selectOneMenu 中使用转换器? [复制]

如何从循环或数组填充JSF selectonemenu

JSF / PrimeFaces使用selectOneMenu将列表中的项目关联起来

JSF 2.0每次从selectOneMenu中选择一个项目时如何显示不同的h:panelGroup

JSF2 <h:selectOneMenu 和 <f:ajax 侦听器在 PrettyFaces 过滤器导航之后未调用