如何在 h:dataTable 中使用 h:selectOneRadio 来选择单行?

Posted

技术标签:

【中文标题】如何在 h:dataTable 中使用 h:selectOneRadio 来选择单行?【英文标题】:How to use h:selectOneRadio in h:dataTable to select single row? 【发布时间】:2012-06-13 17:09:08 【问题描述】:

我在表格中显示了页面列表。每个页面都有属性 homePage 我希望在数据表中有一列单选按钮绑定在这个属性上,并且用户只能检查一个值。如何在服务器端获取此值?

我看到了一些类似下面的例子: http://jforum.icesoft.org/JForum/posts/list/14157.page, 但我想知道在这种情况下最好的做法是什么。

【问题讨论】:

【参考方案1】:

根据JSF spec issue 329,我终于为 JSF 2.3 实现了它。使用新的group 属性,您现在可以在转发器组件中对单选按钮进行分组。

<h:dataTable value="#bean.items" var="item">
    <h:column>
        <h:selectOneRadio group="foo" value="#bean.selectedItem">
            <f:selectItem itemValue="#item" />
        </h:selectOneRadio>
    </h:column>
</h:dataTable>

它将根据 Mojarra 2.3.0-m07 提供。


在 JSF 2.3 之前,这对于标准 JSF &lt;h:selectOneRadio&gt; 来说并非易事。基本上,每一行中的单选按钮需要使用相同的输入 name 相互分组,以便在您选择一个单选按钮时取消选中其他单选按钮。但是它们没有被分组,它们都有自己的name,所以其他单选按钮永远不会被取消选中。

像 PrimeFaces 这样的组件库通过提供一个特殊的属性或列组件解决了这个问题。另请参阅this showcase example,它使用&lt;p:column selectionMode="single"&gt; 生成单个选择列。所选值由&lt;p:dataTable&gt;selection 属性引用。如果您已经在使用组件库并且它已经为您提供了这样的组件,那么您应该使用它。

在标准 JSF &lt;h:dataTable&gt;&lt;h:selectOneRadio&gt; 中,您需要引入如下 javascript 解决方法,取消选中同一列中的所有其他单选按钮:

<h:dataTable value="#bean.items" var="item">
    <h:column>
        <h:selectOneRadio valueChangeListener="#bean.setSelectedItem"
            onclick="dataTableSelectOneRadio(this);">
            <f:selectItem itemValue="null" />
        </h:selectOneRadio>
    </h:column>
    ...
</h:dataTable>

public void setSelectedItem(ValueChangeEvent event) 
    FacesContext context = FacesContext.getCurrentInstance();
    selectedItem = context.getApplication().evaluateExpressionGet(context, "#item", Item.class);

function dataTableSelectOneRadio(radio) 
    var radioId = radio.name.substring(radio.name.lastIndexOf(':'));

    for (var i = 0; i < radio.form.elements.length; i++) 
        var element = radio.form.elements[i];

        if (element.name.substring(element.name.lastIndexOf(':')) == radioId) 
            element.checked = false;
        
    

    radio.checked = true;

【讨论】:

当我在h:selectOneRadio 中使用&lt;f:ajax execute="@this" render="@form" /&gt; 以便valueChangeListener 工作时,单选按钮被选中然后被取消选中,有什么想法吗?我希望选中的收音机保持选中状态,而旧选中的收音机则不选中 这里不需要&lt;f:ajax&gt; 当我点击任何单选按钮时不会触发 valueChangeListener。 你也可以看看这个方法***.com/questions/10970248/… 这也不是本意。只有当您通过命令按钮以通常的方式提交表单时才会触发它。或者您想在选择单选按钮时立即提交表单?你没有要求那个。这样一来,整个 JavaScript 解决方法就没有必要了,答案必须改变。【参考方案2】:

我找到了另一个解决方案,我想与你分享,是使用h:selectBooleanCheckbox,以及BalusC建议的单选JS函数:

            <ace:column id="homePage" headerText="Home Page">
                <h:selectBooleanCheckbox value="#adpage.homePage" onclick="dataTableSelectOneRadio(this);"></h:selectBooleanCheckbox>
            </ace:column>

和 JS:

function dataTableSelectOneRadio(radio) 
var radioId = radio.name.substring(radio.name.lastIndexOf(':'));

for (var i = 0; i < radio.form.elements.length; i++) 
    var element = radio.form.elements[i];

    if (element.name.substring(element.name.lastIndexOf(':')) == radioId) 
        element.checked = false;
               
         

      radio.checked = true;
    

这将只选中一个复选框并更新选中/未选中对象中的布尔属性。

【讨论】:

复选框在 UI 视角中用作单选时会更加混乱,因为它们通常表示多选。您不应该将其用于单选。如果您的唯一目的是保留选定/检查的值,只需使用 value 属性和正确的 &lt;f:selectItem&gt; 值。如何正确使用&lt;h:selectBooleanCheckbox&gt;已经在这里得到解答:***.com/questions/2524514/…【参考方案3】:

selectedRadioButton 变量应该在函数之外声明。

var selectedRadioButton;

function uncheckRadioButtons(radioButton) 
   if (selectedRadioButton != null) 
      selectedRadioButton.checked = false;
   

   selectedRadioButton = radioButton;
   selectedRadioButton.checked = true;

在 xhtml

 <h:selectOneRadio 
        onclick="uncheckRadioButtons(this);">
        <f:selectItem itemValue="null" />
    </h:selectOneRadio>

【讨论】:

以上是关于如何在 h:dataTable 中使用 h:selectOneRadio 来选择单行?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 <h:dataTable> 或 <ui:repeat> 中使用 <h:selectBooleanCheckbox> 来选择多个项目?

如何在 h:dataTable 中实现行编号

在 h:dataTable 中使用 java.util.Map

如何在没有 JSF 标记库(h:datatable 或 ui:repeat)的情况下编写 <table> 标记,但仍使用 JSF 来控制页面流

在 h:dataTable 中忽略 JSF 输入 ID

如何有条件地设置丰富的行:dataTable