ajax_deliver y return

We encourage users to post events happening in the community to the community events group on https://www.drupal.org.
grone2013's picture

Saludos compañeros.

Al trabajar AJAX en Drupal quiero saber de forma correcta cuál es la diferencia entre la función ajax_deliver y retornar en una función callback array('#type' => 'ajax', '#commands' => $commands);

Gracias por la ayuda

Comments

Asumo que la pregunta es

jedihe's picture

Asumo que la pregunta es sobre Drupal 7 :)

No he invocado directamente ajax_deliver, pero tengo entendido que es la función responsable de convertir el render array con comandos ajax en el JSON que se retorna al cliente (junto con cosas internas de Drupal como los nuevos Drupal.settings).

Algunos datos de cómo funciona AJAX para formularios (ruta system/ajax):

system_menu declara la ruta system/ajax (https://api.drupal.org/api/drupal/modules%21system%21system.module/funct...):

<?php
$items
['system/ajax'] = array(
   
'title' => 'AHAH callback',
   
'page callback' => 'ajax_form_callback',
   
'delivery callback' => 'ajax_deliver',
   
'access callback' => TRUE,
   
'theme callback' => 'ajax_base_page_theme',
   
'type' => MENU_CALLBACK,
   
'file path' => 'includes',
   
'file' => 'form.inc',
  );
?>

Lo que se retorne del page callback es procesado por el delivery callback (https://api.drupal.org/api/drupal/includes%21menu.inc/function/menu_exec...):

<?php
...
// Deliver the result of the page callback to the browser, or if requested,
  // return it raw, so calling code can do more processing.
 
if ($deliver) {
   
$default_delivery_callback = (isset($router_item) && $router_item) ? $router_item['delivery_callback'] : NULL;
   
drupal_deliver_page($page_callback_result, $default_delivery_callback);
  }
  else {
    return
$page_callback_result;
  }
...
?>

Ahí se puede ver que el delivery_callback del router_item (hook_menu) es usado si está presente.

Si miramos en más detalle, vemos que el page callback (ajax_form_callback) sí define el array con #type y #commands cuando el resultado del page callback no lo retorna explícitamente (https://api.drupal.org/api/drupal/includes%21ajax.inc/function/ajax_form...):

<?php
...
    if (!(
is_array($result) && isset($result['#type']) && $result['#type'] == 'ajax')) {
     
// Turn the response into a #type=ajax array if it isn't one already.
     
$result = array(
       
'#type' => 'ajax',
       
'#commands' => ajax_prepare_response($result),
      );
    }
...
?>

Según lo anterior, para usar AJAX en un formulario no es obligatorio invocar directamente ajax_deliver, sino simplemente implementar el atributo #ajax (con #wrapper y #callback dentro) y retornar la parte del formulario que se desea refrescar desde el callback. Ahora bien, para un caso donde pudiera ser necesario hacerlo a mano, sugiero replicar la forma en que lo hace la ruta system/ajax (y tener mucho cuidado de no introducir vulnerabilidades XSS/CSRF!).

Una cosa importante: el callback es sólo para retornar la parte del formulario que se desea actualizar, no para hacer tareas de submit. En el módulo de ejemplos se ve claro: http://cgit.drupalcode.org/examples/tree/ajax_example/ajax_example.modul...