9.8.2. Formulaire popup multi-étapes dans Drupal
Dans cet article, nous allons continuer à comprendre le Form API dans Drupal 8 et créer un formulaire multi-étapes. Nous avons déjà créé un formulaire de configuration classique pour le module, le formulaire multi-étapes est créé de manière similaire en utilisant $form_state
pour stocker les données entre les étapes du formulaire.
Des exemples de code sont disponibles sur GitHub :
https://github.com/levmyshkin/drupalbook8
Pour un formulaire multi-étapes, vous devez ajouter une classe de formulaire :
/modules/custom/drupalbook/src/Form/MultiStepForm.php
<?php
/**
* @file
* Contient Drupal\drupalbook\Form\MultiStepForm.
*/
namespace Drupal\drupalbook\Form;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
class MultiStepForm extends FormBase
{
protected $step = 1;
/**
* {@inheritdoc}
*/
protected function getEditableConfigNames()
{
}
/**
* {@inheritdoc}
*/
public function getFormID()
{
return 'multi_step_form';
}
/**
* {@inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state)
{
//$form = parent::buildForm($form, $form_state);
// Ajout d'un div wrapper pour que le Form API puisse mettre à jour le formulaire en AJAX
$form['#prefix'] = '<div id="ajax_form_multistep_form">';
$form['#suffix'] = '</div>';
if ($this->step == 1) {
$form['message-step'] = [
'#markup' => '<div class="step">' . $this->t('Étape 1 sur 2') . '</div>',
];
$form['message-title'] = [
'#markup' => '<h2>' . $this->t('Qui êtes-vous ?') . '</h2>',
];
$form['first_name'] = [
'#type' => 'textfield',
'#title' => $this->t('Prénom'),
'#placeholder' => $this->t('Prénom'),
'#required' => TRUE,
];
$form['last_name'] = [
'#type' => 'textfield',
'#title' => $this->t('Nom'),
'#placeholder' => $this->t('Nom'),
'#required' => TRUE,
];
}
if ($this->step == 2) {
$form['message-step'] = [
'#markup' => '<div class="step">' . $this->t('Étape 2 sur 2') . '</div>',
];
$form['message-title'] = [
'#markup' => '<h2>' . $this->t('Merci d’entrer vos coordonnées ci-dessous :') . '</h2>',
];
$form['phone'] = [
'#type' => 'textfield',
'#title' => $this->t('Téléphone'),
'#placeholder' => $this->t('Téléphone'),
'#required' => TRUE,
];
$form['email'] = [
'#type' => 'email',
'#title' => $this->t('Adresse e-mail'),
'#placeholder' => $this->t('Adresse e-mail'),
'#attributes' => ['class' => ['mail-first-step']],
'#required' => TRUE,
];
$form['subscribe'] = [
'#type' => 'checkbox',
'#title' => $this->t('S’abonner à la newsletter'),
];
$form['agree'] = [
'#markup' => '<p class="agree">' . $this->t('En vous inscrivant, vous acceptez les <a href="@terms">Conditions générales</a> et la <a href="@policy">Politique de confidentialité</a>',
['@terms' => '/terms-and-conditions', '@policy' => '/privacy-policy']) . '</p>',
];
}
if ($this->step == 3) {
$form['message-step'] = [
'#markup' => '<p class="complete">' . $this->t('- Terminé -') . '</p>',
];
$form['message-title'] = [
'#markup' => '<h2>' . $this->t('Merci') . '</h2>',
];
}
if ($this->step == 1) {
$form['buttons']['forward'] = [
'#type' => 'submit',
'#value' => t('Suivant'),
'#prefix' => '<div class="step1-button">',
'#suffix' => '</div>',
'#ajax' => [
// Wrapper créé au début du formulaire
'wrapper' => 'ajax_form_multistep_form',
// Callback pour recharger le formulaire via AJAX
'callback' => '::ajax_form_multistep_form_ajax_callback',
'event' => 'click',
],
];
}
if ($this->step == 2) {
$form['buttons']['forward'] = [
'#type' => 'submit',
'#value' => t('Envoyer'),
'#ajax' => [
'wrapper' => 'ajax_form_multistep_form',
'callback' => '::ajax_form_multistep_form_ajax_callback',
'event' => 'click',
],
];
}
$form['#attached']['library'][] = 'drupalbook/multistep_form';
return $form;
}
/**
* {@inheritdoc}
*/
public function validateForm(array &$form, FormStateInterface $form_state) {
return parent::validateForm($form, $form_state);
}
/**
* {@inheritdoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
if ($this->step == 2) {
$values = $form_state->getValues();
$email = $values['email'];
// Sauvegarder les données ou envoyer un e-mail ici.
}
$this->step++;
$form_state->setRebuild();
}
public function ajax_form_multistep_form_ajax_callback(array &$form, FormStateInterface $form_state) {
return $form;
}
}
Ensuite, nous allons expliquer ce que fait chaque ligne. En attendant, créons une route pour notre formulaire :
/modules/custom/drupalbook/drupalbook.routing.yml
:
drupalbook.multistep_form:
path: '/multistep-form'
defaults:
_form: '\Drupal\drupalbook\Form\MultiStepForm'
_title: 'S’abonner à la newsletter'
requirements:
_permission: 'access content'
Cela créera un formulaire accessible à l’adresse /multistep-form :
Pour que ce formulaire s’ouvre dans une fenêtre popup modale, vous devez ajouter un bloc ou simplement un texte avec une classe use-ajax
spécifique et l’attribut data-dialog-type="modal"
, avec un lien vers la page du formulaire. Vous devrez également activer les bibliothèques suivantes : core/drupal.dialog.ajax
, core/jquery.form
. Si vous faites cela via un bloc, vous obtiendrez le code suivant pour le bouton ouvrant le formulaire dans la popup : modules/custom/drupalbook/src/Plugin/Block/SubscribeFormButton.php
<?php
namespace Drupal\drupalbook\Plugin\Block;
use Drupal\Core\Block\BlockBase;
/**
* Fournit un bouton d’inscription à la newsletter.
*
* @Block(
* id = "drupalbook_subsribe_form_button",
* admin_label = @Translation("S’abonner à la newsletter"),
* )
*/
class SubscribeFormButton extends BlockBase {
/**
* {@inheritdoc}
*/
public function build() {
$text = '<a href="/multistep-form" class="use-ajax" data-dialog-type="modal">S’abonner</a>';
return [
'#markup' => $text,
'#attached' => [
'library' => [
'core/drupal.dialog.ajax',
'core/jquery.form',
],
],
];
}
}
Le formulaire dans la popup ressemblera à ceci :
J’ai aussi connecté une bibliothèque personnalisée depuis le fichier drupalbook.libraries.yml
:
modules/custom/drupalbook/drupalbook.libraries.yml
multistep_form:
css:
css/multistep_form.css: {}
js:
scripts/multistep_form.js: {}
dependencies:
- core/jquery
- core/jquery.once
Il est nécessaire de styliser le formulaire et d’y connecter les plugins jQuery nécessaires. Vous devrez donc créer d’autres fichiers :
modules/custom/drupalbook/css/multistep_form.css
modules/custom/drupalbook/scripts/multistep_form.js
Des exemples de code sont disponibles sur GitHub :
https://github.com/levmyshkin/drupalbook8