É possível substituir mais de um elemento de formulário (wrappers) acionado por apenas um elemento de gatilho #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'];

}

É possível retornar mais de um bit de formulário na função de retorno de chamada, informando a estrutura AJAX que $form['element_to_be_replaced_1']deve substituir <div id="replace_div_1">e $form['element_to_be_replaced_2']deve substituir <div id="replace_div_2">?

Francisco Luz
fonte

Respostas:

73

Em vez de retornar o HTML do elemento único a ser atualizado, seu retorno de chamada ajax pode retornar uma matriz de comandos ajax . Portanto, ele pode retornar dois ajax_command_replace para substituir 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
fonte
2
Este é incrível !! Economizou muito tempo. Muito obrigado :)
Sandesh Yadav
Uma recompensa está chegando em 24 horas.
AyeshK
Teve que alterar o nome da função de retorno de chamada. O uso da função ajax_example_simplest_callback (& ​​$ form, $ form_state) {} me deu a tela branca da morte.
Ghoti 26/07
5

Drupal 8 sintaxe alternativa

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

Uma diferença é que o comando render é descartado, porque o AjaxResponse implementa Drupal \ Core \ Render \ AttachmentsInterface

render ($ form ['element_to_be_replaced_1'])

Adicionar a renderização ainda funciona, mas tive problemas ao atualizar uma tabela TableSelect dessa maneira.

Johann
fonte
Obrigado, funciona. Eu acho que não vai ser sábio para usar render () porque documentações Drupal diz que seu deplicated e não vai estar disponível em Drupal 9
Ngatia Frankline
4

A resposta de Pierre Buyle não funcionou para mim. No entanto, algo como o seguinte funcionou.

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

Observe a chamada para ajax_deliver () , em vez de retornar a matriz de comandos AJAX.

Coiote
fonte
2
Eu acho que você está usando #ajax ['path'] no seu formulário. Nesse caso, em sua implementação hook_menu, você deve usar a propriedade 'deliver callback', isso instruirá o Drupal a renderizar o resultado de retorno de chamada da sua página como comando AJAX em vez de marcação. Mas, usando-o diretamente no retorno de chamada da sua página, você ignora a entrega normal da página do Drupal.
Pierre Buyle