Photo d'un grue floutée
  • 26/04/2019
  • 0 commentaire

Lors d'une manipulation de formulaire, il est assez fréquent de vouloir la main sur la structure HTML. Par défaut les champs s'affichent les uns en dessous des autres avec uniquement le balisage des éléments du formulaire.

Pour gérer facilement la structure HTML d'un Form sous Drupal 8, il faut se tourner vers les thèmes ...

Du cas simple ...

Partie d'un formulaire regroupant les champs par catégories

Les formulaires peuvent très bien n'être qu'une suite de champs alignés verticalement, mais pour un site professionnel ils sont au minimum regroupés par catégories. Les informations personnelles obligatoires, puis les facultatives, les informations précisant la demande de la personnes, des champs libre... afin de donner toute la souplesse possible à l'internaute.

Dans l'exemple ci-contre, il y a deux listes de champs regroupés par catégories. Ceci est un exemple minimale de ce qu'on peut faire avec un template custom au niveau du formulaire.

Au plus complexe ...

Formulaire de configuration complexe

Voici un formulaire beaucoup plus complexe, il peut s'agir d'une page de configuration d'un compte ou d'une fonctionnalité sur un extranet.

La gestion fine du HTML d'un formulaire doit être effectuée lorsque qu'il y a un regroupement de champs dans des onglets, des fieldsets ...
Avec Drupal 8 il est facile de mettre en place des fonctionnalités complexe comme le multistep. Il est donc primordial de pouvoir structurer le formulaire à sa guise.

Bref, tous cela est possible avec les thèmes au seins des formulaires, rentrons un peu plus dans la technique.

Création d'un formulaire

Pour créer un formulaire il faut déclarer une classe dans le dossier mymodule/src/Form/CustomForm.php

Voici la structure minimale de la classe :

<?php

namespace Drupal\mymodule\Form;

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

/**
 * Custom Form
 */
class CustomForm extends FormBase {

  /**
   * {@inheritdoc}
   */
  public function getFormId() {
    return 'mymodule_custom_form';
  }

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state) {
       return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state) {
    
  }
}

Tout les formulaires héritent de la classe FormBase qui implémente elle même FormInterface. Cette dernière oblige les classes "filles" à implémenter 3 méthodes.

  • getFormID() : Retourne une chaîne de caractère afin que le formulaire est un identifiant unique. Il est préférable de construire cet identifiant en précisant le nom du module dans lequel se trouve le formulaire. Cela permet d'identifier rapidement où se trouve la déclaration du formulaire.
  • buildForm() : C'est dans cette méthode que la déclaration des champs du formulaire se fait. Pour plus d'informations à ce sujet vous pouvez consulter la documentation officielle de l'API Form de Drupal 8.
  • submitForm() : Cette méthode est appelée lorsque le formulaire est validé par l'utilisateur. Vous pourrez récupérer les valeurs de l'utilisateur dans l'objet $form_state via ce bout de code.
    • // Récupération de toutes les valeurs saisies dans un tableau
      $values = $form_state->getValues();
      
      // Récupération uniquement d'une valeur précise
      $value = $form_state->getValue('field_name');

       

Gestion du thème

Voici enfin la partie principale de ce billet de blog, comment déclarer un thème et gérer la structure HTML de mon formulaire. Pour faire cela trois étapes sont nécessaires, déclarer le thème, l'indiquer au formulaire et écrire le template du thème.

Déclaration du thème

La déclaration du thème d'un formulaire se fait de la même manière qu'un thème basique, via un hook_theme(). A une petite différence, c'est que l'on ne déclare pas de variables, uniquement un render element.

/**
 *  Implements hook_theme()
 */
function mymodule_theme($existing, $type, $theme, $path) {
  return [
    'mymodule_customform_theme' => [
      'render element' => 'form',
    ],
  ];
}

Le fait de préciser form dans le render element fait que le thème est appelé Drupal fournira le formulaire automatiquement au template.

Fournir l'information au formulaire

Maintenant que le thème est déclaré, il faut donner l'information au formulaire. Pour cela il suffit d'indiquer la ligne suivante dans la méthode buildForm() ou via un form alter.

// Déclarer le nom du thème créé dans le hook_theme()
$form['#theme'] = 'mymodule_customform_theme';

Écriture du template

Le template est un fichier twig à mettre dans le répertoire mymodule/templates et dont le fichier est le nom du thème en remplaçant les underscore '_' par des tirets '-' comme ceci : mymodule-customform-theme.html.twig

Le chemin ainsi que le nom du template est défini de cette façon par défaut. Si vous avez, pour X ou Y raison, besoin d'un chemin ou d'un nom de fichier personnalisé vous pouvez l'indiquer dans la déclaration du thème comme ceci.

/**
 *  Implements hook_theme()
 */
function mymodule_theme($existing, $type, $theme, $path) {
  return [
    'mymodule_customform_theme' => [
      'render element' => 'form',
      'path' => 'mydirectory/templates',
      'template' => 'custom_name_of_my_theme',    
    ], 
  ];
}

Une fois le template créé il n'y à plus qu'à construire le HTML. Il y a quand même deux trois petites informations que vous devez savoir.

Voici un exemple de template de formulaire.

<aside class="mymodule-customform">
    {{ form.form_build_id }}
    {{ form.form_token }}
    {{ form.form_id }}

    <div class="input-group">
        {{ form.input_text_firstname }}
    </div>

    <div class="buttons">
        {{ form.actions }}
    </div>  
</aside>

L'objet form est passé au template, donc si vous avez déclaré un input de type textfield ayant pour nom de clef 'input_text_firstname' vous devez le printer avec twig comme ceci : {{ form.input_text_firstname }}

Pour que le formulaire soit fonctionnel il faut printer trois informations obligatoire. (lignes 2, 3, 4) Celles-ci permettent de savoir quel fichier est envoyé par l'internaute afin d'appelé la bonne classe et ainsi passé dans le bon submitForm().

Réécrire le template du formulaire peut être également fait depuis votre thème général. Par défaut ce sera le template présent dans le module mais si vous déclarez un template avec le même nom dans votre thème principal il sera pris par défaut.

Aller plus loin...

Si votre formulaire est affiché sur sa propre page vous pouvez gérer son titre dynamiquement.