Is it possible to replace more than one form element (wrappers) triggered by only one #ajax trigger element?

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'];

}

Is it possible to return more than one form bit in the callback function telling the AJAX framework that $form['element_to_be_replaced_1'] should replace <div id="replace_div_1"> and $form['element_to_be_replaced_2'] should replace <div id="replace_div_2">?

Answers 3

  • Instead of returning the HTML of the single element to update, your ajax callback can return an array of ajax commands. So it can return two ajax_command_replace to replace each element.

    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']))
        )
      );
    }
    

  • Drupal 8 alternate syntax

    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;
       }
    }
    

    One diffrence is that the render command is dropped, because AjaxResponse implements Drupal\Core\Render\AttachmentsInterface

    render($form['element_to_be_replaced_1'])

    Adding the render still works, but I had problems when updating a TableSelect Table that way.


  • Pierre Buyle's answer did not work for me. However, something like the following worked.

    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);
    }
    

    Note the call to ajax_deliver(), rather than returning the array of AJAX commands.


Related Questions