Utiliser Ajax pour générer du contenu en drupal 7

Publié dans: 

A partir de mon expérience lors de la contribution au développement du module DQuarks qui est pour le moment en phase de validation sous ses deux version 6 et 7, j’ai eu l’occasion d’utiliser Ajax pour l’ajout et la suppression des options pour le composant « multi-choix ».


Dans cet article, je partage avec vous comment on peut passer des paramètres dans la fonction Ajax appelée en drupal 7, en présentant les paramètres d’Ajax (path et callback) les plus utilisés et en mettant l’accent sur l’importance d’Ajax [’path’].

 

Problématique:

Un exemple concis présentant l’objectif de l'article:

 

Dans cet exemple, on liste l’ensemble des réponses possibles pour une question donnée.
- Le bouton « Supprimer » devant chaque entrée permet à l’administrateur de supprimer une réponse.
- Le bouton « Ajouter » permet à l’administrateur d’ajouter une entrée.
L’ajout et la suppression d’une entrée se font via un appel Ajax sans charger toute la page.

Le but est d'identifier l’entrée à supprimer suite à un appel de la fonction Ajax.

 

Explication:

Pour la suppression d’une entrée on doit récupérer l’identifiant de l’entrée sélectionnée et cela ne se fait qu’en passant des paramètres dans la fonction Ajax appelée.
Dans l’exemple présenté ci-dessus, chaque entrée est identifiée par un numéro unique qui s’incrémente.
L’ajout d’une entrée n’impose pas de passer des paramètres.

Pour utiliser Ajax pour un élément spécifique, on doit ajouter la propriété #ajax à ce dernier qui déclenchera un appel Ajax quand il est changé ou cliqué.
Dans notre cas la propriété #ajax est spécifiée dans les deux boutons « Supprimer » et « Ajouter ».

La propriété #ajax supporte plusieurs paramètres. Dans ce qui suit on présente deux paramètres très utiles pour définir la fonction Ajax appelée : #ajax[‘callback’] et #ajax[‘path’] (un des paramètres est nécessaire) .

- #ajax[‘callback’] : indique au système le formulaire qu’on doit appeler après l'appel Ajax.
Ce paramètre définit la fonction à appeler pour gérer l'évènement Ajax côté serveur, qui recevra comme arguments d’entrée les variables $form, et $form_state, et retourne un tableau (le plus souvent un formulaire ou un fragment de formulaire), une chaîne HTML, ou un tableau de commandes Ajax. Si on retourne un tableau ou une chaîne, la valeur va remplacer l'élément d'origine défini dans le paramètre #ajax['wrapper'].

Par défaut, #ajax utilise «system/ajax » comme chemin d'accès qui invoque la fonction ajax_form_callback(), éventuellement l'appel de la fonction nommée dans #ajax['callback'].

Cependant, on peut éventuellement spécifier un chemin différent ou invoquer une fonction différente à appeler, qui peut renvoyer un code HTML mis à jour.

- #ajax['path'] : permet d’implémenter des cas plus avancés que la gestion des formulaires standards.
Ce paramètre est souvent omis et la valeur par défaut est utilisée ("system/ajax"). Ce chemin doit correspondre à un appel de page dans le hook_menu() qui renvoie des données en utilisant la fonction ajax_render(). Si on utilise un chemin d'accès personnalisé, on doit configurer l'entrée de menu et gérer le code de la fonction appelée dans son propre code.

 

Solution:

Les deux éléments sont définis comme suit:

  •  Le bouton « Ajouter »:
 $form['items']["operations"]['add'] = array(
    '#type' => 'submit',
    '#value' => t('Add'),
    '#parents' => array('items', 'operations', 'add'),
    '#submit' => array('dquarks_edit_submit_ajax_example_add_questions'),
    '#ajax' => array(
      'callback' => '_dquarks_edit_submit_ajax_example_questions_ajax_callback',
      'wrapper' => 'all_questions',
      'effect' => 'fade',
    ),
  );

Vu qu’on n’a pas spécifié le paramètre path dans la propriété #ajax, la fonction ajax_form_callback() sera appelée par défaut une fois qu’on clique sur le bouton.
Cette dernière fait appel:
1-  A la fonction drupal_process_form() qui fait appel à son tour à la fonction définie dans le paramètre #submit du bouton.

function dquarks_edit_submit_ajax_example_add_questions($form, &$form_state) {
  $items = array('choices', 'labels', 'notes');
  foreach ($items as $keys) {
    $add[$keys] = $form_state['input']['items'][$keys]['add'];
    unset($form_state['input']['items'][$keys]['add']);
  }
  if (count($form_state['values']['items']['labels']) > 1) {
    $max = 1 + max(array_keys($form_state['values']['items']['labels']));
  }
  else {
    $max = 1 + array_pop(array_keys($form_state['values']['items']['labels']));
  }
  if (!empty($add['labels'])) {
    foreach ($items as $keys) {
      $form_state['values']['items'][$keys][$max] = $add[$keys];
      unset($form_state['values']['items'][$keys]['add']);
    }
  }
  $form_state['rebuild'] = TRUE;
}

2- Puis à la fonction définie dans le paramètre callback.

function _dquarks_edit_submit_ajax_example_questions_ajax_callback($form, $form_state) {
  return $form['items'];
}

Le formulaire par la suite sera rechargé en tenant compte des modifications effectuées.

  • Le bouton « Supprimer »:

L'élément est défini comme suit:

      $form['items']["operations"][$key] = array(
        '#type' => 'submit',
        '#value' => t('Delete'),
        '#parents' => array('items', 'operations', $key),
        '#submit' => array("_dquarks_edit_submit_ajax_example_del_questions"),
        '#ajax' => array(
          'path' => "ajax/callback/" . $key,
          'callback' => '_dquarks_edit_submit_ajax_example_questions_ajax_callback',
          'wrapper' => 'all_questions',
          'effect' => 'fade',
          'method' => 'replace',
        ),
      );

Afin de passer des paramètres dans la fonction ajax appelée, on définit le paramètre 'path'.

On doit dans ce cas configurer l'entrée de menu et gérer le code de la fonction appelée.

// Implements hook_menu()
$items['ajax/callback'] = array(
    'page callback' => 'dquarks_component_edit_callback',
    'access callback' => 'node_access',
    'access arguments' => array('update', 1),
    'type' => MENU_CALLBACK,
  );
  
  $items['ajax/callback/%dquarks_menu_operation_parms'] = array(
    'page callback' => 'dquarks_component_edit_callback',
    'laod arguments' => array(2),
  );

Suite au clic sur le bouton, la fonction définie dans le menu spécifié dans le paramètre 'path' de la propriété #ajax est appelée.
 

function dquarks_component_edit_callback($id) {
  $_POST["del_question"] = $id;
  // Call the submit function.
  $page_callback_result = ajax_form_callback();
  $commands = ajax_prepare_response($page_callback_result);
  $page = array('#type' => 'ajax', '#commands' => $commands);
  ajax_deliver($page);
}

Dans cette fonction, on récupère l’identifiant de l’élément sélectionné et on invoque la fonction ajax_form_callback() qui fait appel:

1- A la fonction définie dans le paramètre submit du bouton « Supprimer »

 

function _dquarks_edit_submit_ajax_example_del_questions($form, &$form_state) {
  $items = array('choices', 'labels', 'notes', 'operations');
  $id = (int) check_plain($_POST['del_question']);
  foreach ($items as $keys) {
    unset($form_state['values']['items'][$keys][$id]);
  }
  $form_state['rebuild'] = TRUE;
}

 

2- Puis à la fonction définie dans le paramètre 'callback'.

 

function _dquarks_edit_submit_ajax_example_questions_ajax_callback($form, $form_state) {
  return $form['items'];
}

 A la fin de la fonction, on fait appel à la fonction ajax_deliver() qui fait appel à son tour à la fonction ajax_render() pour retourner le contenu JSON à afficher dans le navigateur.

 

Ces bouts de code sont inspirés du module DQuarks. Pour plus de détails vous pouvez le télécharger à partir de ce lien.