JSF selectManyCheckbox

El componente JSF h: selectManyCheckbox es una parte importante de JavaServer Faces (JSF) y se utiliza para proporcionar a los usuarios la posibilidad de seleccionar varios elementos de una lista. En esta publicación, discutiremos los conceptos básicos de este componente, como sus atributos y opciones de layout.

Este componente renderiza una tabla HTML que contendrá tantos <input type=»checkbox»> como componentes f: selectItem se hayan agregado a select Many Checkbox en el formulario JSF.

Asignando una cantidad fija de checkboxes

En el primer ejemplo se muestra su utilización agregando una cantidad fija de checkbox mediante la utilización de f: selectItem:

<h:form id="customerForm">
	<h:selectManyCheckbox id="chk-countries" value="#{bean.checkedCountries}">
		<f:selectItem itemValue="argentina" itemLabel="Argentina" />
		<f:selectItem itemValue="uruguay" itemLabel="Uruguay" />
		<f:selectItem itemValue="paraguay" itemLabel="Paraguay" />
		<f:selectItem itemValue="bolivia" itemLabel="Bolivia" />
		<f:selectItem itemValue="peru" itemLabel="Perú" />
	</h:selectManyCheckbox>					
</h:form>

El atributo value de h: selectManyCheckbox contiene una expresión que hace referencia a un array de String en el Managed Bean. Los valores de los checkbox marcados por el usuario se asignarán automáticamente a este array, lo que permitirá manipular los valores seleccionados desde el código Java.

El código HTML generado es el siguiente:

<table id="customerForm:chk-countries">
	<tbody>
        <tr>
            <td>
                <input name="customerForm:chk-countries" id="customerForm:chk-countries:0" value="argentina" type="checkbox">
                <label for="customerForm:chk-countries:0" class=""> Argentina</label>
            </td>
            <td>
                <input name="customerForm:chk-countries" id="customerForm:chk-countries:1" value="uruguay" type="checkbox">
                <label for="customerForm:chk-countries:1" class=""> Uruguay</label>
            </td>
            <td>
                <input name="customerForm:chk-countries" id="customerForm:chk-countries:2" value="paraguay" type="checkbox">
                <label for="customerForm:chk-countries:2" class=""> Paraguay</label>
            </td>
            <td>
                <input name="customerForm:chk-countries" id="customerForm:chk-countries:3" value="bolivia" type="checkbox">
                <label for="customerForm:chk-countries:3" class=""> Bolivia</label>
            </td>
            <td>
                <input name="customerForm:chk-countries" id="customerForm:chk-countries:4" value="peru" type="checkbox">
                <label for="customerForm:chk-countries:4" class=""> Perú</label>
            </td>
	    </tr>
    </tbody>
</table>

Notar que el elemento <table> generado a partir de h: selectManyCheckbox contiene un id compuesto por el id del h: form que contiene al componente, y el id del componente h: selectManyCheckbox:

JSF selectManyCheckbox id

Además, los elementos <input type=»checkbox»> generados tienen un id compuesto por el id del h: form que contiene al componente, el id del componente h: selectManyCheckbox, y un id secuencial:

JSF selectManyCheckbox item id

JSF selectManyCheckbox con una cantidad variable de checkboxes

En el siguiente ejemplo se muestran dos casos en los que el número de checkboxes renderizados en la página puede ser determinado en tiempo de ejecución gracias al componente f: selectItems:

<h:selectManyCheckbox value="#{bean.checkedRivers}" layout="lineDirection">
   <f:selectItems value="#{bean.rivers}" />
</h:selectManyCheckbox>
					
<h:selectManyCheckbox value="#{bean.checkedLakes}" styleClass="page-direction-table" layout="pageDirection">
   <f:selectItems value="#{bean.lakes}" />
</h:selectManyCheckbox>

El atributo value de los componentes f: selectItems contienen una expresión que hace referencia a un java.util.List y un java.util.Map, respectivamente. Estos últimos son cargados durante la inicialización del Managed Bean, pudiendo hacerse con datos recuperados, por ejemplo, de una base de datos. A los fines de este ejemplo se hardcodean estos datos en el método init():

@Named("bean")
@RequestScoped
public class ExampleBean implements Serializable {

	private List<SelectItem> rivers;
	private Map<String, String> lakes;
	
	private String[] checkedCountries;
	private String[] checkedRivers;	
	private String[] checkedLakes;	
	
	@PostConstruct
	public void init() {
		this.rivers = new ArrayList<SelectItem>();
		this.rivers.add(new SelectItem("parana", "Paraná"));
		this.rivers.add(new SelectItem("limay", "Limay"));
		this.rivers.add(new SelectItem("salado", "Salado"));
		this.rivers.add(new SelectItem("uruguay", "Uruguay"));
		
		this.lakes = new HashMap<String, String>();
		this.lakes.put("san-roque", "San Roque");
		this.lakes.put("argentino", "Argentino");
		this.lakes.put("nahuel-huapi", "Nahuel Huapi");
		
	}


    //getters & setters

	
	public String getCheckedCountriesString() {
		return Arrays.toString(this.checkedCountries);
	}

	public String getCheckedRiversString() {
		return Arrays.toString(this.getCheckedRivers());
	}
	
	public String getCheckedLakesString() {
		return Arrays.toString(this.getCheckedLakes());
	}
	
	
	public String aceptar() {
		return "result";
	}

}

Notar como se utiliza el atributo layout para determinar la orientación de la alineación de los checkboxes renderizados en pantalla. El valor ‘lineDirection‘ (que es el valor por defecto) generará el elemento <table> de manera tal que los checkboxes queden dispuestos de forma horizontal. Si por el contrario, se utiliza el valor ‘pageDirection‘ el elemento <table> generado permitirá que los checkboxes se dispongan de forma vertical:

JSF selectManyCheckbox layout

La página de resultados hace referencia a los métodos getCheckedCountriesString(), getCheckedRiversString() y getCheckedLakesString() para visualizar los valores seleccionados.

JSF selectManyCheckbox result

Agregar validaciones personalizadas a selectManyCheckbox

Puede agregar validación avanzada al componente h:selectManyCheckbox en JSF usando un validador personalizado. En el siguiente ejemplo se usa el validador personalizado countrySelectedValidator con el componente h:selectManyCheckbox. Si no se seleccionan opciones, el validador lanzará una ValidatorException con un mensaje de error relevante, que será mostrado por el componente h:message.

<h:selectManyCheckbox id="chk-countries" value="#{bean.checkedCountries}">
	<f:selectItem itemValue="argentina" itemLabel="Argentina" />
	<f:selectItem itemValue="uruguay" itemLabel="Uruguay" />
	<f:selectItem itemValue="paraguay" itemLabel="Paraguay" />
	<f:selectItem itemValue="bolivia" itemLabel="Bolivia" />
	<f:selectItem itemValue="peru" itemLabel="Perú" />
	<f:validator validatorId="countrySelectedValidator"/>
</h:selectManyCheckbox>	
package com.jcodepoint.validator;

import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.validator.FacesValidator;
import javax.faces.validator.Validator;
import javax.faces.validator.ValidatorException;

@FacesValidator("countrySelectedValidator")
public class CountrySelectedValidator implements Validator {

	@Override
	public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException {
		String[] selectedValues = (String[]) value;

		if(selectedValues == null || selectedValues.length  == 0) {
			FacesMessage message = new FacesMessage("Debe seleccionar al menos un país.");
			throw new ValidatorException(message);
		}
	}
}

Este es solo un ejemplo de cómo puede implementar una validación avanzada para h:selectManyCheckbox. Dependiendo de sus requisitos específicos, es posible que deba agregar lógica adicional o personalización para adaptarlo a su caso de uso.

Conclusión

Como vimos en este artículo , el componente JSF selectManyCheckbox es una herramienta potente y versátil para proporcionar a los usuarios la capacidad de seleccionar varios elementos de una lista. Es fácil de usar y se puede personalizar fácilmente para adaptarse a las necesidades de cualquier proyecto. Con su amplia gama de atributos y opciones de layout, el componente selectManyCheckbox es una parte invaluable del framework JSF y se puede usar para crear experiencias de usuario más interactivas.


Te puede interesar:

JSF selectOneListbox

El componente JSF selectOneListbox se renderizará, una vez procesada la página, como un elemento de HTML. En este artículo se explica su uso.

Seguir leyendo →

JSF selectOneRadio

El componente JSF selectOneRadio se renderizará, una vez procesada la página, como una tabla de HTML con un grupo de radio buttons.

Seguir leyendo →