viernes, 21 de octubre de 2011

Peticiones Ajax en Tapestry (II)

Apache Tapestry
Como comentaba en la entrada Peticiones Ajax en Tapestry para hacerlas no es necesaria ni una sola linea de javascript. En la entrada Peticiones Ajax en Tapestry expliqué como hacer una petición Ajax que actualizaba un fragmento de una página y como hacer un petición Ajax que devolviese datos en Json para ser procesados en el cliente.

Pero el soporte para las peticiones Ajax de Tapestry no se queda en esos dos casos. Otro escenario habitual en las páginas es la necesidad de actualizar más de una región de una misma página con una única petición. Para ello Tapestry proporciona la clase MultiZoneUpdate (en la versión 5.3 será desaconsejado su uso en favor del uso de AjaxResponseRenderer) que será el objeto que deberemos devolver en el método del evento que atiende la petición. Este objeto contendrá las referencias de las zonas que queremos actualzar en la página y los nuevos contenidos a mostrar en ellas, Tapestry se encargará en el cliente de actualizarlas automaticamente por nosotros sin que tengamos que hacer nada más.

Veámoslo con un ejemplo.

<t:zone t:id="usuarioZone" update="show">
    <t:if test="service.usuario">
        <span>${service.usuario.login} (<a t:id="cerrarSesion" t:type="actionlink">Cerrar sesion</a>)</span>
        <p:else><span>Invitado (<a t:type="pagelink" page="index">Iniciar sesión/Registrarse</a>)</span></p:else>
 </t:if>
</t:zone>
...
<t:zone t:id="formularioZone" update="show">
 <t:if test="!service.usuario">
  <t:form t:id="usuarioRegistradoForm" zone="datosZone">
   <t:html5textfield type="email" value="urForm.usuario" validate="required" placeholder="Usuario"/>
   <t:html5textfield type="password" value="urForm.contrasena" validate="required" placeholder="Contraseña"/><br/>    
   <t:submit t:id="usuarioRegistradoSubmit" value="Iniciar sesión" class="btn"/>
  </t:form>
 </t:if>

 <t:if test="service.usuario">
  <t:form t:id="cerrarSesionUsuarioRegistradoForm">
   ${service.usuario.login}<br/>
   <t:submit t:id="cerrarSesionUsuarioRegistradoSubmit" value="Cambiar de usuario" class="btn"/>
  </t:form>
 </t:if>
</t:zone>

Object onSubmitFromUsuarioRegistradoForm() throws IOException {
// Registrar al usuario (service.getUsuario() devolverá el objeto que representa al usuario)
...
 if (!service.getRequestGlobals().getRequest().isXHR()) {
  return null;
 }

 MultiZoneUpdate mzu = new MultiZoneUpdate("formularioZone", formularioZone.getBody()).add("usuarioZone", sesionZone.getBody());;

 return mzu;
}

En el ejemplo hay definidas dos zonas (usuarioZone, formularioZone) que son los componentes definidos con <t:zone>. Las zonas representan fragmentos de página cuyo contenido puede ser actualizado por una petición Ajax. Cuando se envía el formuario formularioZone se llama al método onSubmitFromUsuarioRegistradoForm en el cual comprobamos si la petición es una petición Ajax (service.getRequestGlobals().getRequest().isXHR()) si no lo es se actualizará toda la página pero todo seguirá funcionando, si lo es se devuelve un objeto MultiZoneUpdate y se actualizarán las zonas formularioZone y usuarioZone con el contenido de los propios componentes formularioZone y sesionZone aunque podríamos actualizarlas con el contenidos de otros componentes. Los eventos lanzados por Tapestry siguen por defecto una convención que es on[Evento]From[Componente] aunque podrímos darle el nombre que queramos si utilizamos anotaciones.

En Tapestry pasar de una aplicación no Ajax a una Ajax es muy sencillo basta insertar las zonas y en los métodos de los eventos devolver las zonas y contenidos con las que las queremos actualizar. Otro punto importante a destacar y que contribuye a facilitar la adición del soporte Ajax es que el contenido con el que se actualizan las zonas no lo tenemos que saparar en archivos individuales ni supondrá una reestructuración drástica en los archivos del proyecto como tendríamos que hacer en otros frameworks. También a destacar es que esta funcionalidad de actualizar dos fragmentos o zonas de una página no está presente en otros frameworks de por sí donde normalmente cada petición Ajax actualiza un único fragmento. El soporte en Tapestry para trabajar con Ajax es ¡sencillo y excelente!, de lo mejor que hay.

Nota: A partir de la versión 5.3 la clase MultiZoneUpdate ha sido marcada como obsoleta y la nueva clase y método a utilizar es ajaxResponseRenderer.addRender.

Referencia:
Peticiones Ajax en Tapestry
Documentación sobre Apache Tapesty