jsf - type - Cómo hacer seleccionado h: selectOneRadio of h: dataTable permanece seleccionado en la devolución de datos?
select radio jsf (1)
En circunstancias normales como esta:
<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>
Seleccionar un botón de radio disecciona el otro y el botón de radio permanecerá seleccionado en la devolución de datos. (cuando se representa la misma vista)
Sin embargo, cuando se trata de un componente <h:dataTable>
como <h:dataTable>
, la selección se pierde.
Considera el fragmento:
<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>
Con la disección de los otros botones de radio cuando se selecciona un botón de radio que se implementa mediante JavaScript simple-
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;
}
}
}
}
Ahora presiona el botón de enviar, respuesta:
Verás que el botón de radio se selecciona en la devolución de datos. ¿Cómo resolver este inconveniente?
Sé muy bien que esto se debe a que este atributo de componente itemValue
es null
:
<f:selectItem itemValue="null"/>
Este truco es un remanente de JSF 1.x / 2.0 / 2.1 cuando no era posible usar un <h:selectOneRadio>
para la selección de una sola fila en a <h:dataTable>
. Este truco se originó en mi artículo de blog de 10 años Usando Datatables - Seleccione la fila por el botón de radio .
El problema principal es que los botones de radio HTML se agrupan en función de su atributo de name
, por lo que el navegador web sabe cuáles otros deseleccionar cuando se selecciona uno. Pero JSF genera por diseño una diferente para cada elemento <h:dataTable>
, con el índice de fila inline y, por lo tanto, no se pueden agrupar y, por lo tanto, la solución alternativa basada en JavaScript.
Desde JSF 2.2, con la nueva característica de elementos y atributos de paso a través , es posible forzar el atributo de name
al valor de su elección y capturar el elemento seleccionado a través de un helper <h:inputHidden>
. Esto se desarrolla en otro artículo de blog mío del año anterior: Diseño personalizado con h: selectOneRadio en JSF 2.2 . El artículo usa <ui:repeat>
como ejemplo, esto se puede volver a escribir a <h:dataTable>
como se muestra a continuación.
<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);
}
// ...
}
Y sí, el botón de opción seleccionado permanece seleccionado en la devolución de datos de esta manera. También puede pasar entidades enteras, esto solo requiere un convertidor en <h:inputHidden>
.