如何选择h:selectOneRadio of h:dataTable在回发时保持选中状态?

时间:2016-06-26 12:33:25

标签: jsf datatable jsf-2.2 selectoneradio

在正常情况下:

  <h:form>           
    <h:selectOneRadio value="#{bean.gender}">
        <f:selectItem itemValue="Male" itemLabel="Male" />
        <f:selectItem itemValue="Female" itemLabel="Female" />
        <f:selectItem itemValue="Other" itemLabel="Other" />
    </h:selectOneRadio>
    <h:commandButton value="Submit" action="#{bean.action}" />
  </h:form>

选择一个单选按钮可以解析另一个单选按钮。单选按钮将在回发中保持选中状态。 (当呈现相同的视图时)

但是,当我们处理像<h:dataTable>这样的迭代组件时,选择会丢失。

考虑一下代码段:

        <h:form id="hashMapFormId">           
            <b>HASH MAP:</b>
            <h:dataTable value="#{playersBean.dataHashMap.entrySet()}" var="t" border="1">
                <h:column>
                    <f:facet name="header">Select</f:facet>
                    <h:selectOneRadio id="radiosId" onclick="deselectRadios(this.id);" 
                                        value="#{playersBean.select}">
                        <f:selectItem itemValue="null"/>
                    </h:selectOneRadio>
                </h:column> 
            </h:dataTable>
            <h:commandButton value="Show Hash Map Selection" 
                             action="#{playersBean.showSelectedPlayer()}" />
        </h:form>

通过简单的JavaScript实现选择一个单选按钮时,通过分析其他单选按钮 -

            function deselectRadios(id) {

                var f = document.getElementById("hashMapFormId");
                for (var i = 0; i < f.length; i++)
                {
                    var e = f.elements[i];
                    var eid = e.id;
                    if (eid.indexOf("radiosId") !== -1) {
                        if (eid.indexOf(id) === -1) {
                            e.checked = false;
                        } else {
                            e.checked = true;
                        }
                    }
                }
            }

解雇GET请求:
enter image description here

选择一个单选按钮:
enter image description here

现在按下提交按钮,回复:
enter image description here

您会看到在回发时取消选中单选按钮。如何解决这个缺点?

我非常清楚这是因为此组件属性itemValuenull

<f:selectItem itemValue="null"/>

1 个答案:

答案 0 :(得分:2)

当在<h:selectOneRadio>中无法使用<h:dataTable>进行单行选择时,此技巧是JSF 1.x / 2.0 / 2.1的遗留问题。这个技巧起源于我10年前的博客文章Using Datatables - Select row by radio button

根本问题是,HTML单选按钮基于其name属性进行分组,因此webbrowser知道在选择一个时要取消选择哪些其他按钮。但是JSF按设计为每个<h:dataTable>项生成不同的一个,行内联索引,因此无法对它们进行分组,因此基于JavaScript的解决方法。

由于JSF 2.2具有新的passthrough elements and attributes功能,因此可以强制name属性为您选择的值,并通过帮助程序<h:inputHidden>捕获所选项目。我在去年的另一篇博客文章中充实了这一点:Custom layout with h:selectOneRadio in JSF 2.2。本文使用<ui:repeat>作为示例,可以将其重写为<h:dataTable>,如下所示。

<h:form>
    <h:dataTable value="#{bean.items}" var="item">
        <h:column>
            <input type="radio" jsf:id="item" a:name="#{hiddenItem.clientId}"
                value="#{item.id}" a:checked="#{item.id eq bean.selectedItemId ? 'checked' : null}" />
        </h:column>
        <h:column>#{item.id}</h:column>
        <h:column>#{item.name}</h:column>
    </h:dataTable>
    <h:inputHidden id="selectedItem" binding="#{hiddenItem}" value="#{bean.selectedItemId}"
        rendered="#{facesContext.currentPhaseId.ordinal ne 6}" />
    <h:commandButton id="submit" value="Submit" action="#{bean.submit}" />
</h:form>

@Named
@ViewScoped
public class Bean implements Serializable {

    private List<Item> items;
    private Long selectedItemId;

    // ...

    public void submit() {
        System.out.println("Selected item ID: " + selectedItemId);
    }

    // ...
}

是的,选中的单选按钮在回发时保持选中状态。您也可以传递整个实体,这只需要<h:inputHidden>上的转换器。