¿Es posible reemplazar más de un elemento de formulario (wrappers) activado por un solo elemento desencadenante #ajax?

52
function ajax_example_simplest($form, &$form_state) {

  //This is my ajax trigger element
  $form['element_trigger'] = array(
    '#type' => 'select',
    '#options' => array(
      'one' => 'one',
      'two' => 'two',
      'three' => 'three',
    ),
    '#ajax' => array(
      'callback' => 'ajax_example_simplest_callback',

      /** Q: Can I somehow declare more than one wrapper? **/
      //Say for instance, something like:
      'wrapper' => array('replace_div_1', 'replace_div_2'),

     ),
  );

  //replace_div_1
  $form['element_to_be_replaced_1'] = array(
    '#type' => 'textfield',
    '#title' => t("My conditional field one"),
    '#prefix' => '<div id="replace_div_1">',
    '#suffix' => '</div>',
  );


 //... more form elements here

  //replace_div_2
  $form['element_to_be_replaced_2'] = array(
    '#type' => 'textfield',
    '#title' => t("My conditional field two"),
    '#prefix' => '<div id="replace_div_2">',
    '#suffix' => '</div>',
  );
  return $form;
}

function ajax_example_simplest_callback($form, $form_state) {

  //... do my stuff here


  //normally I would return only the form bit for replacing a single wrapper
  //declared in the trigger element, like this:
  return $form['element_to_be_replaced_blahblah'];

}

¿Es posible devolver más de un bit de formulario en la función de devolución de llamada que indica al marco AJAX que $form['element_to_be_replaced_1']debería reemplazar <div id="replace_div_1">y $form['element_to_be_replaced_2']debería reemplazar <div id="replace_div_2">?

Francisco luz
fuente

Respuestas:

73

En lugar de devolver el HTML del elemento único para actualizar, su devolución de llamada ajax puede devolver una matriz de comandos ajax . Por lo tanto, puede devolver dos ajax_command_replace para reemplazar cada elemento.

function ajax_example_simplest_callback(&$form, $form_state) {
  return array(
    '#type' => 'ajax',
    '#commands' => array(
      ajax_command_replace("#replace_div_1", render($form['element_to_be_replaced_1'])),
      ajax_command_replace("#replace_div_2", render($form['element_to_be_replaced_2']))
    )
  );
}
Pierre Buyle
fuente
2
¡Esta es increíble! Ahorró mucho tiempo. Muchas gracias :)
Sandesh Yadav
Te llegará una recompensa en 24 horas.
AyeshK
Tuve que cambiar el nombre de la función de devolución de llamada. El uso de la función ajax_example_simplest_callback (& ​​$ form, $ form_state) {} me dio la pantalla blanca de la muerte.
Ghoti
5

Sintaxis alternativa de Drupal 8

use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Ajax\ReplaceCommand;

class name extends FormBase{
   function ajax_example_simplest(array $form, FormStateInterface &$form_state) {
       $response = new AjaxResponse();
       $response->addCommand(new ReplaceCommand("#replace_div_1", ($form['element_to_be_replaced_1'])));
       $response->addCommand(new ReplaceCommand("#replace_div_2", ($form['element_to_be_replaced_2'])));
       return $response;
   }
}

Una diferencia es que el comando de renderizado se cae, porque AjaxResponse implementa Drupal \ Core \ Render \ AttachmentsInterface

render ($ form ['element_to_be_replaced_1'])

Agregar el renderizado aún funciona, pero tuve problemas al actualizar una tabla TableSelect de esa manera.

Johann
fuente
Gracias funciona. Creo que no sería prudente usar render () porque las documentaciones de Drupal dicen que está duplicado y no estará disponible en Drupal 9
Ngatia Frankline
4

La respuesta de Pierre Buyle no funcionó para mí. Sin embargo, algo como lo siguiente funcionó.

function ajax_example_simplest_callback(&$form, $form_state) {
    $commands = array();
    $commands[] = ajax_command_replace("#replace_div_1", render($form['element_to_be_replaced_1']));
    $commands[] = ajax_command_replace("#replace_div_2", render($form['element_to_be_replaced_2']));
    $page = array('#type' => 'ajax', '#commands' => $commands);
    ajax_deliver($page);
}

Tenga en cuenta la llamada a ajax_deliver () , en lugar de devolver la matriz de comandos AJAX.

Coyote
fuente
2
Supongo que estás usando #ajax ['ruta'] en tu formulario. En ese caso, en su implementación hook_menu, debe usar la propiedad 'entregar devolución de llamada', esto le indicará a Drupal que presente el resultado de devolución de llamada de su página como un comando AJAX en lugar de marcado. Pero al usarlo directamente en la devolución de llamada de su página, omite la entrega normal de la página de Drupal.
Pierre Buyle