Symfony 1.2, la guía definitiva

11.4. Parámetros para la ejecución remota

Todos los helpers de Ajax descritos anteriormente pueden utilizar otros parámetros, además de los parámetros update y url. El array asociativo con los parámetros de Ajax puede modificar el comportamiento de la ejecución remota y del procesamiento de las respuestas.

11.4.1. Actualizar elementos diferentes en función del estado de la respuesta

Si la ejecución remota no devuelve un resultado, los helpers pueden actualizar otro elemento distinto al elemento que se actualizaría en caso de una respuesta satisfactoria. Para conseguirlo, solo es necesario indicar como valor del parámetro update un array asociativo que establezca los diferentes elementos que se actualizan en caso de respuesta correcta (success) y respuesta incorrecta (failure). Se trata de una técnica eficaz cuando una página contiene muchas interacciones de Ajax y una única zona de notificación de errores. El listado 11-16 muestra el uso de esta técnica.

Listado 11-16 - Actualización condicional en función de la respuesta

<div id="error"></div>
<div id="respuesta"></div>
<p>¡Hola Mundo!</p>
<?php echo link_to_remote('Borrar este artículo', array(
    'update'   => array('success' => 'respuesta', 'failure' => 'error'),
    'url'      => 'articulo/borrar?id='.$articulo->getId(),
)) ?>

Truco Solo las respuestas de servidor cuyo código de estado HTTP sea de tipo error (500, 404 y todos los códigos diferentes de 2XX) provocan la actualización del elemento preparado para las respuestas erroneas. Las acciones que devuelven el valor sfView::ERROR no se consideran como erróneas. De esta forma, si se requiere que una acción de tipo Ajax devuelva una respuesta errónea, se debe ejecutar $this->getResponse()->setStatusCode(404) con cualquier código HTTP de error.

11.4.2. Actualizar un elemento según su posición

Al igual que sucede con el helper update_element_function(), se puede especificar el elemento a actualizar de forma relativa respecto de otro elemento mediante el parámetro position. El listado 11-17 muestra un ejemplo.

Listado 11-17 - Uso del parámetro position para modificar el lugar donde se muestra la respuesta

<div id="respuesta"></div>
<p>¡Hola Mundo!</p>
<?php echo link_to_remote('Borrar este artículo', array(
    'update'   => 'respuesta',
    'url'      => 'articulo/borrar?id='.$articulo->getId(),
    'position' => 'after',
)) ?>

En esta ocasión, la respuesta de la petición Ajax se muestra después (after) del elemento cuyo atributo id es igual a respuesta; es decir, se muestra después del <div> y antes del <p>. De esta forma, se pueden realizar varias peticiones Ajax y ver como se acumulan todas las respuestas después del elemento que se actualiza.

El parámetro position puede tomar uno de los siguientes valores:

  • before: antes del elemento
  • after: después del elemento
  • top: antes que cualquier otro contenido del elemento
  • bottom: después de todos los contenidos del elemento

11.4.3. Actualizar un elemento en función de una condición

Las peticiones Ajax pueden tomar un parámetro adicional que permite que el usuario de su consentimiento antes de ejecutar la petición con el objeto XMLHttpRequest, como muestra el listado 11-18.

Listado 11-18 - Uso del parámetro confirm para solicitar el consentimiento del usuario antes de realizar la petición remota

<div id="respuesta"></div>
<?php echo link_to_remote('Borrar este artículo', array(
    'update'   => 'respuesta',
    'url'      => 'articulo/borrar?id='.$articulo->getId(),
    'confirm'  => '¿Estás seguro?',
)) ?>

En este caso, se muestra al usuario un cuadro de diálogo de JavaScript con el mensaje "¿Estás seguro?" cuando pincha sobre el enlace. La acción articulo/borrar solo se ejecuta si el usuario da su consentimiento a esta petición pulsando sobre el botón de "Aceptar".

La ejecución de la petición remota también se puede condicionar a que se cumpla una condición JavaScript evaluada en el navegador del usuario, mediante el parámetro condition, tal y como se muestra en el listado 11-19.

Listado 11-19 - Ejecución de petición remota condicionada a que se cumpla una condición probada en el lado del cliente

<div id="respuesta"></div>
<?php echo link_to_remote('Borrar este artículo', array(
    'update'    => 'respuesta',
    'url'       => 'articulo/borrar?id='.$articulo->getId(),
    'condition' => "$('IDelemento') == true",
)) ?>

11.4.4. Determinando el método de una petición Ajax

Las peticiones Ajax se realizan por defecto mediante un método POST. Si se quiere realizar una petición Ajax que no modifica los datos o si se quiere mostrar un formulario que incluye validación como resultado de una petición Ajax, se puede utilizar el método GET. La opción method modifica el método de la petición Ajax, como muestra el listado 11-20.

Listado 11-20 - Modificando el método de una petición Ajax

<div id="respuesta"></div>
<?php echo link_to_remote('Borrar este artículo', array(
    'update'    => 'respuesta',
    'url'       => 'articulo/borrar?id='.$articulo->getId(),
    'method'    => 'get',
)) ?>

11.4.5. Permitiendo la ejecución de un script

Si la respuesta de una petición Ajax incluye código JavaScript (el código es la respuesta del servidor y se incluye en el elemento indicado por el parámetro update) por defecto no se ejecuta ese código. El motivo es el de reducir la posibilidad de ataques remotos y para permitir al programador autorizar la ejecución del código de la respuesta después de comprobar el contenido del código.

Para permitir la ejecución de los scripts de la respuesta del servidor, se debe utilizar la opción script. El listado 11-21 muestra un ejemplo de una petición Ajax remota que autoriza la ejecución del código JavaScript que forme parte de la respuesta.

Listado 11-21 - Permitiendo la ejecución de un script en una respuesta Ajax

<div id="respuesta"></div>
<?php
  // Si la respuesta de la acción articulo/borrar contiene código
  // JavaScript, se ejecuta en el navegador del usuario
  echo link_to_remote('Borrar este artículo', array(
    'update'    => 'respuesta',
    'url'       => 'articulo/borrar?id='.$articulo->getId(),
    'script'    => 'true',
)) ?>

Si la plantilla remota contiene helpers de Ajax (como por ejemplo remote_function()), estas funciones PHP generan código JavaScript, que no se ejecuta a menos que se indique la opción script => true.

Nota Cuando se permite la ejecución de los scripts de la respuesta remota, el código fuente del código remoto no se puede ver ni siquiera con una herramienta para visualizar el código generado. Los scripts se ejecutan pero su código no se muestra. Se trata de un comportamiento poco habitual, pero completamente normal.

11.4.6. Creando callbacks

Una desventaja importante de las interacciones creadas con Ajax es que son invisibles al usuario hasta que se actualiza la zona preparada para las notificaciones. Por tanto, si se produce un error de servidor o la red está congestionada, los usuarios pueden pensar que su acción se ha realizado correctamente cuando en realidad aun no ha sido procesada. Este es el motivo por el que es muy importante notificar al usuario sobre los eventos que se producen a lo largo de una interacción creada con Ajax.

Por defecto, cada petición remota es un proceso asíncrono durante el que se pueden ejecutar varias funciones JavaScript de tipo callback (por ejemplo para indicar el progreso de la petición). Todas las funciones de callback tienen acceso directo al objeto request, que contiene a su vez el objeto XMLHttpRequest. Los callback que se pueden definir se corresponden con los eventos que se producen durante una interacción de Ajax:

  • before: antes de que se inicie la petición
  • after: justo después de que se inicie la petición y antes de que se cargue
  • loading: cuando se está cargando la respuesta remota en el navegador
  • loaded: cuando el navegador ha terminado de cargar la respuesta remota
  • interactive: cuando el usuario puede interaccionar con la respuesta remota, incluso si no se ha terminado de cargar
  • success: cuando XMLHttpRequest está completo y el código HTTP de estado corresponde al rango 2XX
  • failure: cuando XMLHttpRequest está completo y el código HTTP de estado no corresponde al rango 2XX
  • 404: cuando la petición devuelve un error de tipo 404
  • complete: cuando XMLHttpRequest está completo (se ejecuta después de success o failure, si alguno de los 2 está definido)

El ejemplo más habitual es el de mostrar un indicador de tipo Cargando... mientras la petición remota se está ejecutando y ocultarlo cuando se recibe la respuesta. Para incluir este comportamiento, solo es necesario añadir los parámetros loading y complete a la petición Ajax, tal y como muestra el listado 11-22.

Listado 11-22 - Uso de callbacks en Ajax para mostrar y ocultar un indicador de actividad

<div id="respuesta"></div>
<div id="indicador">Cargando...</div>
<?php echo link_to_remote('Borrar este artículo', array(
    'update'    => 'respuesta',
    'url'       => 'articulo/borrar?id='.$articulo->getId(),
    'loading'  => "Element.show('indicador')",
    'complete' => "Element.hide('indicador')",
)) ?>

Los métodos show(), hide() y el objeto Element son otras de las utilidades proporcionadas por la librería Prototype.