Image représentant des portes avec une toute jaune.
  • 11/06/2019
  • 0 commentaire

L'API Ajax de Drupal offre de multiples possibilités pour dynamiser les formulaires. Dans cet article, nous allons voir comment proposer des valeurs dynamiques à vos utilisateurs.

Dans un précédent billet nous avons vu comment personnaliser le thème d'un formulaire. Regardons maintenant comment faire en sorte que notre joli formulaire soit le plus simple d'utilisation possible.

Les champs textes font partie des champs où l'utilisateur peut mettre n’importe quelle valeur, il peut être intéressant de le guider lors de sa saisie en lui fournissant des valeurs possibles. Ceci est faisable grâce à l’auto-complétion proposée par l'API Ajax de Drupal 8.

C'est techniquement simple car avec une option sur l'élément et une route le tour est joué. Préparons le terrain avec la déclaration du formulaire et sa route.

Déclaration de la route contenant le formulaire

Pour notre exemple nous allons partir sur un formulaire custom. Créons tout d'abord une route qui affichera le formulaire dans le thème d'administration.

Dans votre module, créé ou édité le fichier mymodule.routing.yml afin d'ajouter les lignes suivantes :

example_ajax_autocomplete.custom_form:
  path: '/admin/example-form'
  defaults:
    _form: '\Drupal\example_ajax_autocomplete\Form\ExampleForm'
    _title: 'Example Form'
  requirements:
    _permission: 'access content'

Ces informations indiquent que Drupal devra retourner le formulaire ExampleForm lorsqu'un utilisateur se rendra sur la page /admin/example-form.

Développons maintenant le formulaire qui sera affiché dans la page

<?php

namespace Drupal\example_ajax_autocomplete\Form;

use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;

class ExampleForm extends FormBase {

  /**
   * Returns a unique string identifying the form.
   *
   * The returned ID should be a unique string that can be a valid PHP function
   * name, since it's used in hook implementation names such as
   * hook_form_FORM_ID_alter().
   *
   * @return string
   *   The unique string identifying the form.
   */
  public function getFormId() {
    return 'example_ajax_autocomplete_form';
  }

  /**
   * Form constructor.
   *
   * @param array $form
   *   An associative array containing the structure of the form.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The current state of the form.
   *
   * @return array
   *   The form structure.
   */
  public function buildForm(array $form, FormStateInterface $form_state) {
    $form['textfield_autocomplete'] = [
      '#type' => 'textfield',
      '#title' => $this->t('Autocomplete field'),
      '#autocomplete_route_name' => 'example_ajax_autocomplete.route_autocomplete',
      '#autocomplete_route_parameters' => [
        'entity_type' => 'blog',
      ],
    ];

    return $form;
  }

  /**
   * Form submission handler.
   *
   * @param array $form
   *   An associative array containing the structure of the form.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The current state of the form.
   */
  public function submitForm(array &$form, FormStateInterface $form_state) {
    // Custom submit code
  }
}

Formulaire ultra basique possédant un champ de type textfield auquel on définit deux attributs dédiés à l’auto-complétion. L'option obligatoire est #autocomplete_route_name. Il s'agit du nom machine de la route qui sera appelée pour construire la liste de suggestions.

Le paramètre #autocomplete_route_parameters est utilisé pour passer des paramètres entre la définition du champ et le callback générant la liste de suggestions.

Étape finale : Créer le callback de l'auto-complétion

Déclaration de la route

Comme mis plus dans le formulaire, il faut déclarer une route qui appellera un contrôleur spécifique.

example_ajax_autocomplete.route_autocomplete:
  path: '/entity_reference_autocomplete/{entity_type}'
  defaults:
    _controller: '\Drupal\example_ajax_autocomplete\Controller\AutocompleteController::handleAutocomplete'
  requirements:
    _access: 'TRUE'

Écriture du contrôlleur

<?php

namespace Drupal\example_ajax_autocomplete\Controller;

use Drupal\Core\Controller\ControllerBase;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;

/**
 * Defines a route controller for entity autocomplete form elements.
 */
class AutocompleteController extends ControllerBase {



  public function handleAutocomplete(Request $request, $entity_type) {
    $results = [];

      // @todo: Apply logic for generating results based on typed_string and other
      // arguments passed.
      for ($i = 0; $i < 6; $i++) {
        $results[] = [
          'value' => $entity_type.'_' . $i,
          'label' => $entity_type.' - N°' . $i,
        ];
      }

    return new JsonResponse($results);

  }

}

Le contrôleur déclare l'objet Request comme premier argument puis vous avez la possibilité de définir vos paramètres personnels présents dans l'url. Faîtes le traitement métier que vous avez besoin mais la valeur de retour sera toujours la même. Il faut que ce soit un tableau clé/valeur. La valeur sera affiché dans le textfield alors que la clé sera la valeur présente dans le $form_state du submit.

Aperçu du rendus d'un champ autocomplétion

Voici un aperçu d'un champ utilisant l’auto-complétion. Ce système ajoute une vraie plus-value à vos formulaire lorsqu'ils sont spécifiques.

 

Information complémentaire

Pour ne pas avoir un affichage bizarre, il est conseillé de désactiver l'auto-complétion des navigateurs lorsque l'on veut mettre en place ce système. Pour cela il suffit d'ajouter l'attribut autocomplete="off" sur le textfield en question.

  $form['textfield_autocomplete'] = [
      '#type' => 'textfield',
      '#title' => $this->t('Autocomplete field'),
      '#autocomplete_route_name' => 'example_ajax_autocomplete.route_autocomplete',
      '#autocomplete_route_parameters' => [
        'entity_type' => 'blog',
      ],
      '#attributes' => [
        'autocomplete' => 'off',
      ],
    ];

 

 

Lien du répertoire Git de l'exemple utilisé dans ce billet : https://gitlab.com/Mixalis/drupal-8-ajax-autocomplete