Gestión de eventos en el cliente con el soporte de Ajax de RichFaces.
0. Índice de contenidos.
- 1. Introducción.
- 2. Entorno.
- 3. El atributo onComplete.
- 4. Condicionando el evento.
- 5. Referencias.
- 6. Conclusiones.
1. Introducción
En este tutorial vamos a proponer una solución sencilla a la necesidad de provocar un evento en el cliente cuando termine el procesamiento de una petición en el servidor, con el soporte de
Ajax (A4JSF) de
RichFaces.
Como digo, la solución es sencilla, si bien, después vamos a complicarla condicionando el evento en el cliente al procesamiento correcto o no de la petición en el servidor.
Para más información sobre RichFaces podéis consultar el resto de tutoriales que tenemos en adictos, un buen comienzo puede ser el de Introducción a RichFaces… 😉
2. Entorno.
El tutorial está escrito usando el siguiente entorno:
- Hardware: Portátil MacBook Pro 17′ (2.93 GHz Intel Core 2 Duo, 4GB DDR3 SDRAM).
- Sistema Operativo: Mac OS X Snow Leopard 10.6.1
- Jboss Seam 2.2.0.GA.
- RichFaces 3.3.3.CR1
- Maven 2.2.1.
- Eclipse 3.5: Ganymede, con IAM (plugin para Maven).
- Apache Tomcat 6.0.20 con la jdk 1.5.
3. El atributo onComplete.
El objetivo es renderizar en el cliente un botón que al pulsarse se deshablite y provoque un evento vía Ajax en el servidor, tras la respuesta del servidor mostrará un mensaje al cliente, una alerta para simplificar el ejemplo, y se volverá a habilitar.
La solución es la siguiente:
<a4j:form id="reportForm"> <h:panelGrid columns="3"> <h:outputLabel id="labelForReference" for="reference" value="Referencia"> <h:inputText id="reference" value="#{productReportCtrl.reference}" required="true"> <a4j:support event="onblur" reRender="generate" /> </h:inputText> <a4j:commandButton id="generate" value="#{messages['action.generateReport']}" action="#{productReportCtrl.generate}" oncomplete="alert('Informe generado correctamente');this.disabled=false;" onclick="this.disabled=true;" /> </h:panelGrid> </a4j:form>
Ya había dicho que la solución era sencilla, basta con añadir al componente de acción el atributo onComplete y programar el evento que se ejecutará cuando termine el procesamiento de la petición.
Vamos a leer algo más el código:
- línea 1: incluimos un componente de formulario con el soporte de ajax,
- línea 3: incluimos un componente que renderiza una tabla con tres columnas,
- línea 5: incluimos un componente de etiqueta que pinta un texto para indicar el contenido del siguiente componente,
- línea 7 y siguientes: añadimos un componente de entrada de texto para incluir la referencia a un producto (por ejemplo), parámetro que recibirá el managedBean cuando reciba la petición,
- línea 11 y siguientes: el componente de acción que provoca la invocación al método generate del managedBean productReportCtrl, quien en función de la referencia del producto realizará la lógica de negocio necesaria,
- línea 16: cerramos el componente que renderiza la tabla,
- línea 18: cerramos el componente que renderiza el formulario,
4. Condicionando el evento.
Como os comentaba en la introducción vamos a complicarlo algo más, condicionando el evento en el cliente al procesamiento correcto o no de la petición en el servidor.
Este sería el código del correspondiente managedBean, con el soporte de anotaciones de Jboss Seam:
@Name("productReportCtrl") @Scope(ScopeType.SESSION) public class ProductReportCtrl { @In protected StatusMessages statusMessages; private String reference; public String getReference(){ return reference; } public void setReference(String reference){ this.reference=reference; } public void generate(){ if (reference == notFound()){ statusMessages.addFromResourceBundle(Severity.ERROR, "action.msg.error"); return; } // TODO: invocar a la lógica de negocio que genera el informe } private boolean notFound(){ // TODO: invocar la lógica de negocio que comprueba que la referencia existe } }
Y ahí va el código del xhtml:
<a4j:form id="reportForm"> <h:panelGrid columns="3"> <h:outputLabel id="labelForReference" for="reference" value="Referencia"> <h:inputText id="reference" value="#{productReportCtrl.reference}" required="true"> <a4j:support event="onblur" reRender="generate" /> </h:inputText> <a4j:commandButton id="generate" value="#{messages['action.generateReport']}" action="#{productReportCtrl.generate}" data="#{facesContext.maximumSeverity.ordinal ge 2}" oncomplete="if(data == false) { alert('Informe generado correctamente'); } else { alert('Se ha producido un error en la generación') } " /> </h:panelGrid> </a4j:form>
Hemos introducido en el componente de acción el atributo data que puede recoger un valor de cualquier managedBean o de cualquier variable de contexto publicada en el entorno de renderización de la página. El atributo acepta notación JSON, pero
a nosotros solo nos interesa asignarle el resultado de una condición que evalúa si existe algún error en el contexto de JSF cuya criticidad sea mayor que WARNING (#{facesContext.maximumSeverity.ordinal ge 2}:
el atributo maximumSeverity de la clase FacesContext almacena la mayor criticidad de los mensajes encolados con una referencia a un item de la clase Severity, nosotros hacemos uso del ordinal de la enumeración).
Con ello en el atributo onComplete podemos añadir una condición en base al contenido de ese data que nos permita mostrar un mensaje u otro, para el objetivo del tutorial basta, pero podríamos hacer uso de un componente de ventana modal
que pintase los errores que encolamos en el managedBean y mostrarlo o no mostrarlo.
5. Referencias.
- Introducción a RichFaces
- http://livedemo.exadel.com/richfaces-demo/richfaces/commandButton.jsf?tab=info&cid=250770
- http://seamframework.org/Community/SeamJQueryIntegration
- http://www.icefaces.org/JForum/posts/list/9799.page
6. Conclusiones.
Nos resulta bastante útil tener este nivel de control sobre los eventos y respuestas frente a estos eventos que nos proporcionan las librerías de componentes JSF con las que trabajamos día a día.
Si os veis en la necesidad en algún momento, espero que os haya servido de ayuda.
Un saludo.
Jose
Personalmente, creo que explicas muy bien los conceptos que transmiten, y que son interesantes.
Pero veo que en JSF ando muy pez para seguirte…. a ver si logro ponerme las pilas más adelante, aunque, en mi caso, trabajo con Struts 1.3.8…. Espero que se pongan las pilas a nivel técnico, pero ya sabes que, lo que funciona, para qué tocarlo, ¿no? 🙂