En ocasiones es necesario comparar los valores de varios campos de un formulario, realizar sobre ellos una validación de forma conjunta o comprobar si existe un registro en base de datos que contiene todos los valores de los campos antes de realizar una acción.
Para realizar esta validación hemos incorporado a FundeWeb el componente validateForm. Para utilizarlo solo es necesario incluir la etiqueta <fw:validateForm > al final del formulario a evaluar y crear un validador JSF personalizado que contendrá la lógica de la validación.
Para aplicaciones con FundeWeb 1.5 acceda a la siguiente wiki.
Para utilizar el componente validateForm deberemos introducir en el encabezado de nuestra pantalla el espacio de nombres correspondiente a este tag:
xmlns:fw="http://www.um.es/atica/fundeweb"
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:f="http://java.sun.com/jsf/core" xmlns:h="http://java.sun.com/jsf/html" xmlns:s="http://jboss.org/schema/seam/taglib" xmlns:p="http://primefaces.org/ui" xmlns:pe="http://primefaces.org/ui/extensions" xmlns:fw="http://www.um.es/atica/fundeweb"> ... ...
Posteriormente, para poder utilizarlo lo primero que tenemos que hacer es crear un formulario, ya que es requerido para su funcionamiento. Una vez creado el formulario basta con utilizar el componente de la siguiente manera:
<h:form id="locationForm"> <s:decorate id="decoradorCity" template="/layout/editLine.xhtml"> <s:decorate template="/layout/edit.xhtml"> <p:inputText id="cityId" value="#{miBean.city}" /> </s:decorate> </s:decorate> <s:decorate id="decoradorState" template="/layout/editLine.xhtml"> <s:decorate template="/layout/edit.xhtml"> <p:inputText id="stateId" value="#{miBean.state}" /> </s:decorate> </s:decorate> <s:decorate id="decoradorZip" template="/layout/editLine.xhtml"> <s:decorate template="/layout/edit.xhtml"> <p:inputText id="zipId" value="#{miBean.zip}" /> </s:decorate> </s:decorate> <p:commandButton id="submit" value="Submit" actionListener="#{miBean.submitPost}" update="decoradorCity, decoradorState, decoradorZip" /> <fw:validateForm validatorId="locationValidator" showFieldMessages="true" showGlobalMessages="true"/> </h:form>
Para finalizar, es necesario crear el validador JSF que realiza la validación. La clase java para el validador debe extender la clase abstracta FormValidator incluida en la librería Fundeweb Tags.
La clase FormValidator implementa las interfaces javax.faces.validator.Validator y org.primefaces.validate.ClientValidator, y proporciona algunos métodos para simplificar el uso de los componentes y mensajes en el validador.
@FacesValidator(ValidadorLocation.NAME) public class ValidadorLocation extends FormValidator { private Logger log = Logger.getLogger(ValidadorLocation.class); public static final String NAME = "locationValidator"; public static final String ID_STATE = "stateId"; public static final String ID_CITY = "cityId"; public static final String ID_ZIP = "zipId"; @Override public Map<String, Object> getMetadata() { return null; } @Override public String getValidatorId() { return ValidadorLocation.NAME; } @Override public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException { try { // Establece la lista de componentes setComponentes((Map<String, UIInput>) value); // Recupera los componentes UIInput UIInput inputState = getComponente(ID_STATE); UIInput inputCity = getComponente(ID_CITY); UIInput inputZip = getComponente(ID_ZIP); // Recupera los valores introducidos (según el tipo de dato del value del componente) String state = (String) inputState.getValue(); String city = (String) inputCity.getValue(); long zip = (long) inputZip.getValue(); /** * LÓGICA DE LA VALIDACIÓN */ // Si la condición de validación no se cumple se lanza la excepción ValidatorException if (![condición validación]) { throw new ValidatorException(FacesMessages.createFacesMessage(FacesMessage.SEVERITY_ERROR, "ejemplo.mensaje.validacion", null, state, city, zip)); } } catch (ClassCastException c) { // Muestra mensaje de error en caso de no encontrar un ID throw new ValidatorException(new FacesMessage(FacesMessage.SEVERITY_ERROR, "ejemplo.mensaje.classCastValue", null)); } } }
setComponentes((Map<String, UIInput>) value);
Es posible utilizar varias veces el componente validateForm en el mismo formulario. Cada componente usará su validador JSF propio. El orden en el que se definan los componentes en la pantalla, será el orden en el que se ejecuten las validaciones.
Si un formulario tiene diversas comprobaciones que realizar, es recomendable realizar cada comprobación de forma independiente en un componente validateForm aparte (con sus correspondiente validador JSF), especificando en cada componente los campos exactos implicados en cada validación.
Para más información, consulte con su MNCS (juanmiguel.bernal@ticarum.es, ramon.ginel@ticarum.es).