AjaxSingle: el partialSubmit de RichFaces.

0
22360

AjaxSingle: el partialSubmit de RichFaces.

0. Índice de contenidos.


1. Introducción

Después de haber vistro una breve
introducción a RichFaces
y conocer el soporte que proporciona para Ajax de la mano de
Ajax4JSF, en este tutorial
vamos a examinar la posibilidad de hacer uso del atributo ajaxSingle que funciona como el atributo partialSubmit de ICEfaces,
de modo que, asignado a un componente, se submite el valor del mismo al controlador iniciando un ciclo de vida JSF completo, que
se aplicará únicamente a dicho componente.

La diferencia entre ICEfaces y RichFaces, es que el primero extiende los componentes de la implementación básica de JSF, de modo que
tiene su propio <ice:inputText, sin embargo RichFaces no, con lo que dicho atributo no se puede asignar
directamente al componente, hay que hacer uso de un sengundo componente no visual que imprime el soporte para Ajax.

En la redacción de este tutorial se da por hecho que el lector tiene experiencia en JSF y tiene nociones de RichFaces e ICEfaces.


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
  • RichFaces 3.3.2.GA
  • Maven 2.2.1.
  • Eclipse 3.5: Ganymede, con IAM (plugin para Maven).
  • Apache Tomcat 6.0.20 con la jdk 1.5.


3. Inyectando ajax a componentes JSF.

Sobre la base del ejemplo visto en la
introducción a RichFaces vamos a
añadir al formulario algún componente adicional, inyectando sobre los mismos la funcionalidad ajax que comentamos:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
	  xmlns:f="http://java.sun.com/jsf/core"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:a4j="https://ajax4jsf.dev.java.net/ajax"
      xmlns:c="http://java.sun.com/jsp/jstl/core"  
      xmlns:rich="http://richfaces.org/rich"  
      >
	<f:view>
    <rich:panel>
        <f:facet name="header">
        	<h:outputText value="RichFaces ajaxSingle Demo" />
        </f:facet>
        
		<a4j:form>
			<h:panelGrid columns="2">
				<h:outputLabel value="Nombre" for="name"/>
				<h:inputText id="name" value="#{bean.name}" required="true">
			      <a4j:support ajaxSingle="true" event="onblur" reRender="outputContainer"/>
				</h:inputText>
				<h:outputLabel value="Apellidos" for="surname"/>
				<h:inputText id="surname" value="#{bean.surname}" required="true">
			      <a4j:support ajaxSingle="true" event="onblur" reRender="outputContainer"/>
				</h:inputText>
				<h:outputLabel value="NIF" for="nif"/>
				<h:inputText id="nif" value="#{bean.nif}">
					<a4j:support ajaxSingle="true" event="onblur" reRender="outputContainer"/>
				</h:inputText>
				<h:outputLabel value="Fecha de nacimiento" for="birthDay"/>
				<rich:calendar id="birthDay" datePattern="d/M/yyyy HH:mm" value="#{bean.birthDay}"> 
					<a4j:support ajaxSingle="true" event="onchanged" reRender="outputContainer"/>
				</rich:calendar>
				<h:panelGroup />
				<h:commandButton action="none" value="Asignar" />
			</h:panelGrid>
	
			

			
			<rich:spacer height="10px"/>
			
			<rich:separator height="5px"/>
			<rich:spacer height="20px"/>
			<h:panelGrid columns="2" id="outputContainer">
			<h:outputLabel value="Nombre: " /><h:outputText value="#{bean.name}"/>
			<h:outputLabel value="Apellidos: " /><h:outputText value="#{bean.surname}"/>
			<h:outputLabel value="NIF: " /><h:outputText value="#{bean.nif}"/>
			<h:outputLabel value="Fecha de nacimiento: " /><h:outputText value="#{bean.birthDay}"/>
			</h:panelGrid>
	
		</a4j:form>
		
		</rich:panel>
	</f:view>
</html>	

El resultado es que, conforme vamos introduciendo valor a los campos del formulario, el mismo se va submitiendo al servidor mediante una petición en
segundo plano a través de Ajax, pasándo por todo el ciclo de vida de JSF, únicamente para el componente que se submite.

AjaxSingle de RichFaces

Tenemos en la parte inferior una serie de campos de salida que muestran los valores que submitimos y podemos comprobar que los mismos cambian
conforme vamos introduciendo datos en los campos de entrada del formulario.

Con todo ello podríamos realizar validaciones en el servidor con la apariencia de validaciones en el cliente (como ocurre con los campos nombre y apellidos),
puesto que no se recarga toda la página.


4. Nuestro propio partialSubmit con el soporte de Ajax4JSF y facelets.

Vamos a reducir el código de nuestras páginas haciendo uso del soporte de facelets para la generación de nuestra propia tag library a través de la
creación de componentes por composición.

Ya hemos comprobado que funciona la submisión en segundo plano y la recarga, con lo que nos vamos a olvidar de la parte inferior con los campos de salida
y, como consecuencia, del atributo reRender.

Bajo WEB-INF/facelets/tags crearemos un fichero inputText.xhtml con el siguiente código:

<?xml version="1.0" encoding="UTF-8"?>

<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page"
	xmlns:ui="http://java.sun.com/jsf/facelets"
	xmlns:h="http://java.sun.com/jsf/html"
	xmlns:f="http://java.sun.com/jsf/core"
	xmlns:c="http://java.sun.com/jstl/core"
	xmlns:a4j="https://ajax4jsf.dev.java.net/ajax"
	xmlns:rich="http://richfaces.org/rich">

	<ui:composition>
		<!-- The id attribute is optional. empty by default -->
		<c:if test="#{empty id}">
			<c:set var="id" value="" />
		</c:if>
		<!--  The label attribute is optional. Generate it if it is missing. -->
		<c:if test="#{empty label}">
			<c:set var="label" value="#{entity.class.simpleName}.#{field}" />
		</c:if>
		<!-- The required attribute is optional. false by default -->
		<c:if test="#{empty required}">
			<c:set var="required" value="false" />
		</c:if>
		<!-- The partialSubmit attribute is optional. false by default -->
		<c:if test="#{empty partialSubmit}">
			<c:set var="partialSubmit" value="false" />
		</c:if>
		<!-- The reRender attribute is optional. empty by default -->
		<c:if test="#{empty reRender}">
			<c:set var="reRender" value="" />
		</c:if>
		
		<!-- label -->
		<h:panelGroup>
			<h:outputLabel id="labelFor#{id}" for="#{id}"
				value="#{label}:" />
			<h:outputText styleClass="required" rendered="#{required}">*</h:outputText>
		</h:panelGroup>

		<!-- input component -->
		<h:panelGroup>
			<h:inputText id="#{id}" value="#{value}"
				required="#{required}">
				<c:if test="#{partialSubmit}">
					<a4j:support ajaxSingle="true" event="onblur" />
				</c:if>
				<ui:insert />
			</h:inputText>
		</h:panelGroup>
		
		<!-- message -->
		<h:panelGroup>
			<rich:message id="messageFor#{id}" for="#{id}"
				fatalLabelClass="fatal" errorLabelClass="error"
				warnLabelClass="warn" infoLabelClass="info" />
		</h:panelGroup>

	</ui:composition>

</jsp:root>

Encapsula un componente de etiqueta con la descripción del campo que informa, además, de la obligatoriedad del mismo, el propio componente de entrada, y un componente que muestra
los errores asociados a este.

Generaremos nuestra propia librería de tags, creando un fichero autentia.taglib.xml en el mismo directorio con el siguiente contenido:

<?xml version="1.0"?>
<!DOCTYPE facelet-taglib PUBLIC "-//Sun Microsystems, Inc.//DTD
Facelet Taglib 1.0//EN" "facelet-taglib_1_0.dtd">
<facelet-taglib>
	<namespace>http://www.autentia.com/richFaces/facelets</namespace>
	<tag>
		<tag-name>inputText</tag-name>
		<source>inputText.xhtml</source>
	</tag>
</facelet-taglib>

Registramos la librería en el web.xml con el siguiente parámetro de contexto:

	<context-param>
		<param-name>facelets.LIBRARIES</param-name>
		<param-value>/WEB-INF/facelets/tags/autentia.taglib.xml</param-value>
	</context-param>

Y ya podemos hacer uso de nuestros tags en las páginas que lo requieran, el código de nuestra página quedaría como sigue

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
	  xmlns:f="http://java.sun.com/jsf/core"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:a4j="https://ajax4jsf.dev.java.net/ajax"
      xmlns:c="http://java.sun.com/jsp/jstl/core"  
      xmlns:rich="http://richfaces.org/rich"  
      xmlns:tnt="http://www.autentia.com/richFaces/facelets">
	<f:view>
    <rich:panel>
        <f:facet name="header">
        	<h:outputText value="RichFaces ajaxSingle Demo" />
        </f:facet>
        
		<a4j:form>
			<h:panelGrid columns="3">
				
				<tnt:inputText id="name" label="Nombre" value="#{bean.name}" required="true" 
					partialSubmit="true"/>
				<tnt:inputText id="surname" label="Apellidos" value="#{bean.surname}" required="true" 
					partialSubmit="true"/>
				<tnt:inputText id="nif" label="NIF" value="#{bean.nif}"
					 partialSubmit="true"/>

				<h:outputLabel value="Fecha de nacimiento" for="birthDay"/>
				<rich:calendar id="birthDay" datePattern="d/M/yyyy HH:mm" value="#{bean.birthDay}">
					<a4j:support ajaxSingle="true" event="onchanged" reRender="outputContainer"/>
				</rich:calendar>
				<rich:messages for="birthDay" />
				
				<h:panelGroup />
				<h:commandButton action="none" value="Asignar" />
				<h:panelGroup />

			</h:panelGrid>
	
		</a4j:form>
		
		</rich:panel>
	</f:view>
</html>	

Bastante menos código para crear los campos del formulario. Deberíamos continuar con el calendario y con cada componente de formulario que vayamos utilizando.

Indirectamente estamos encapsulando la librería de componentes con la que realmente trabajamos.


5. Referencias.


6. Conclusiones.

El soporte de ajax no es nativo en los componentes de RichFaces, se debe añadir un componente de Ajax4JSF, pero nos da más control sobre qué partes de la página deben repintarse.
Son dos puntos de vista distintos, tener el control o no tenerlo, puesto que con ICEfaces, precisamente de lo que te despreocupas es de eso mismo.

Con facelets podemos encapsular parte del problema y reducir el código de nuestras páginas xhtml. Es imprescindible el uso de un sistema de plantillas,
usemos la tecnología que usemos para la vista.

Un saludo.

Jose

jmsanchez@autentia.com

DEJA UNA RESPUESTA

Por favor ingrese su comentario!

He leído y acepto la política de privacidad

Por favor ingrese su nombre aquí

Información básica acerca de la protección de datos

  • Responsable:
  • Finalidad:
  • Legitimación:
  • Destinatarios:
  • Derechos:
  • Más información: Puedes ampliar información acerca de la protección de datos en el siguiente enlace:política de privacidad