Est-il possible de remplacer plusieurs éléments de formulaire (wrappers) déclenchés par un seul élément déclencheur #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'];

}

Est-il possible de renvoyer plusieurs bits de formulaire dans la fonction de rappel en indiquant au framework AJAX qu'il $form['element_to_be_replaced_1']convient de remplacer <div id="replace_div_1">et de $form['element_to_be_replaced_2']remplacer <div id="replace_div_2">?

Francisco Luz
la source

Réponses:

73

Au lieu de renvoyer le code HTML de l'élément unique à mettre à jour, votre rappel ajax peut renvoyer un tableau de commandes ajax . Donc, il peut renvoyer deux ajax_command_replace pour remplacer chaque élément.

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
la source
2
C'est génial !! Économisé beaucoup de temps. Merci beaucoup :)
Sandesh Yadav
Une prime arrive sur votre chemin dans 24 heures.
AyeshK
J'ai dû changer le nom de la fonction de rappel. Utiliser la fonction ajax_example_simplest_callback (& ​​$ form, $ form_state) {} m'a donné l'écran blanc de la mort.
Ghoti le
5

Drupal 8 Syntaxe alternative

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

Une différence est que la commande de rendu est supprimée, car AjaxResponse implémente Drupal \ Core \ Render \ AttachmentsInterface.

render ($ form ['element_to_be_replaced_1'])

L'ajout du rendu fonctionne toujours, mais j'ai eu des problèmes lors de la mise à jour d'une TableSelect Table de cette façon.

Johann
la source
Merci ça marche. Je pense qu'il ne sera pas sage d'utiliser render () car Drupal documentations dit qu'il est déplacé et ne sera pas disponible dans Drupal 9
Ngatia Frankline
4

La réponse de Pierre Buyle n'a pas fonctionné pour moi. Cependant, quelque chose comme ce qui suit a fonctionné.

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

Notez l'appel à ajax_deliver () plutôt que de renvoyer le tableau de commandes AJAX.

Coyote
la source
2
Je suppose que vous utilisez #ajax ['chemin'] dans votre formulaire. Dans ce cas, dans votre implémentation hook_menu, vous devez utiliser la propriété 'deliver callback', cela donnera à Drupal le rendu de votre résultat de rappel de page sous forme de commande AJAX au lieu de balisage. Mais en l’utilisant directement dans votre rappel de page, vous contournez la diffusion de page Drupal normale.
Pierre Buyle