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

5
我有一个页面列表显示在表格中。每个页面都有一个homePage属性,我想在datatable中添加一个单选按钮列来绑定此属性,用户只能选择一个值。如何在服务器端获取此值?
我看到了一些类似以下链接的示例:http://jforum.icesoft.org/JForum/posts/list/14157.page,但我想知道在这种情况下最佳实践是什么。
3个回答

21

根据JSF规范问题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 <h:selectOneRadio>并不容易实现这个功能。基本上,每一行中的单选按钮需要使用相同的输入名称进行分组,以便在选择一个单选按钮时取消选择其他单选按钮。但是它们没有被分组,它们都有自己的name属性,因此其他单选按钮永远不会被取消选择。

像PrimeFaces这样的组件库通过提供特殊的属性或列组件来解决这个问题。请参见此示例,该示例使用<p:column selectionMode="single">生成一个单选列。所选值由<p:dataTable>selection属性引用。如果您已经使用组件库,并且它已经为您提供了这样的组件,请使用它。

在使用标准JSF <h:dataTable><h:selectOneRadio>时,您需要使用以下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内使用<f:ajax execute="@this" render="@form" />以使valueChangeListener生效时,单选按钮会被选中然后再次取消选中,请问有什么想法吗?我想要被选中的单选按钮保持选中状态,而旧选择的则应该取消选中。 - Mahmoud Saleh
这里不需要使用 <f:ajax> - BalusC
当我点击任何单选按钮时,valueChangeListener不会被触发。 - Mahmoud Saleh
2
这也不是本意。它仅在通过命令按钮以通常的方式提交表单时触发。或者你想在选择单选按钮时立即提交表单吗?你没有要求那样做。那样整个JavaScript解决方法都是不必要的,答案也必须更改。 - BalusC
@BalusC 这段代码非常有帮助,但是我对JSF不是很熟悉...您能否解释一下"value="#{bean.items}" var="item"的含义?value和var包含什么? - Twaha Mehmood
显示剩余3条评论

0

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>

0

我找到了另一个解决方案,想要与您分享,就是使用 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;
    }

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


1
当作为单选时,复选框在UI方面更加令人困惑,因为它们通常表示多个选择。您不应将其用于单选。如果您的唯一目的是保留所选/已选值,请使用value属性和适当的<f:selectItem>值。如何正确使用<h:selectBooleanCheckbox>已在此处回答:https://dev59.com/TXE85IYBdhLWcg3w9onw#2524832 - BalusC

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