9.8.2. Meerstaps pop-up formulier in Drupal
In dit artikel gaan we verder met het begrijpen van de Form API in Drupal 8 en maken we een meerstapsformulier. We hebben al het gebruikelijke configuratieformulier voor de module gemaakt, het meerstapsformulier wordt op een vergelijkbare manier gemaakt door $form_state te gebruiken om gegevens tussen de formulierstappen op te slaan.
Voorbeelden van de code kunnen worden gevonden op github:
https://github.com/levmyshkin/drupalbook8
Voor een meerstapsformulier moet je een formulierklasse toevoegen:
/modules/custom/drupalbook/src/Form/MultiStepForm.php
<?php
/**
* @file
* Bevat 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);
// Voeg een wrapper-div toe die door de Form API wordt gebruikt om het formulier via AJAX bij te werken
$form['#prefix'] = '<div id="ajax_form_multistep_form">';
$form['#suffix'] = '</div>';
if ($this->step == 1) {
$form['message-step'] = [
'#markup' => '<div class="step">' . $this->t('Stap 1 van 2') . '</div>',
];
$form['message-title'] = [
'#markup' => '<h2>' . $this->t('Wie ben je?') . '</h2>',
];
$form['first_name'] = [
'#type' => 'textfield',
'#title' => $this->t('Voornaam'),
'#placeholder' => $this->t('Voornaam'),
'#required' => TRUE,
];
$form['last_name'] = [
'#type' => 'textfield',
'#title' => $this->t('Achternaam'),
'#placeholder' => $this->t('Achternaam'),
'#required' => TRUE,
];
}
if ($this->step == 2) {
$form['message-step'] = [
'#markup' => '<div class="step">' . $this->t('Stap 2 van 2') . '</div>',
];
$form['message-title'] = [
'#markup' => '<h2>' . $this->t('Voer hieronder je contactgegevens in:') . '</h2>',
];
$form['phone'] = [
'#type' => 'textfield',
'#title' => $this->t('Telefoon'),
'#placeholder' => $this->t('Telefoon'),
'#required' => TRUE,
];
$form['email'] = [
'#type' => 'email',
'#title' => $this->t('E-mail adres'),
'#placeholder' => $this->t('E-mail adres'),
'#attributes' => array('class' => array('mail-first-step')),
'#required' => TRUE,
];
$form['subscribe'] = [
'#type' => 'checkbox',
'#title' => $this->t('Abonneer op nieuwsbrief'),
];
$form['agree'] = [
'#markup' => '<p class="agree">' . $this->t(' Door je aan te melden ga je akkoord met de <a href="@terms">Algemene Voorwaarden</a> en <a href="@policy">Privacybeleid</a>',
array('@terms' => '/terms-and-conditions', '@policy' => '/privacy-policy')) . '</p>',
];
}
if ($this->step == 3) {
$form['message-step'] = [
'#markup' => '<p class="complete">' . $this->t('- Voltooid -') . '</p>',
];
$form['message-title'] = [
'#markup' => '<h2>' . $this->t('Dank je wel') . '</h2>',
];
}
if ($this->step == 1) {
$form['buttons']['forward'] = array(
'#type' => 'submit',
'#value' => t('Volgende'),
'#prefix' => '<div class="step1-button">',
'#suffix' => '</div>',
'#ajax' => array(
// We geven de wrapper door die we aan het begin van het formulier hebben gemaakt
'wrapper' => 'ajax_form_multistep_form',
// We geven een callbackfunctie door die we later zullen gebruiken om het formulier voor de gebruiker weer te geven
'callback' => '::ajax_form_multistep_form_ajax_callback',
'event' => 'click',
),
);
}
if ($this->step == 2) {
$form['buttons']['forward'] = array(
'#type' => 'submit',
'#value' => t('Verstuur'),
'#ajax' => array(
// We geven de wrapper door die we aan het begin van het formulier hebben gemaakt
'wrapper' => 'ajax_form_multistep_form',
// We geven een callbackfunctie door die we later zullen gebruiken om het formulier voor de gebruiker weer te geven
'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'];
// Gegevens opslaan of e-mail verzenden hier.
}
$this->step++;
$form_state->setRebuild();
}
public function ajax_form_multistep_form_ajax_callback(array &$form, FormStateInterface $form_state) {
return $form;
}
}
Vervolgens gaan we begrijpen wat elke van deze regels doet. Laten we intussen een route voor ons formulier aanmaken:
/modules/custom/drupalbook/drupalbook.routing.yml:
drupalbook.multistep_form:
path: '/multistep-form'
defaults:
_form: '\Drupal\drupalbook\Form\MultiStepForm'
_title: 'Abonneer je op de nieuwsbrief'
requirements:
_permission: 'toegang inhoud'
Dit maakt een formulier aan op /multistep-form:
Om dit formulier in een pop-upvenster te openen, moet je een blok of gewoon tekst toevoegen met een specifieke use-ajax-klasse en het attribuut data-dialog-type="modal", met een link naar de formulierpagina. Je moet ook de volgende bibliotheken inschakelen: core/drupal.dialog.ajax, core/jquery.form. Als je dit via het blok doet, krijg je de volgende code voor de formulieropen-knop in de pop-up:modules/custom/drupalbook/src/Plugin/Block/SubscribeFormButton.php
<?php
namespace Drupal\drupalbook\Plugin\Block;
use Drupal\Core\Block\BlockBase;
/**
* Biedt een knop voor aanmelden voor de nieuwsbrief.
*
* @Block(
* id = "drupalbook_subsribe_form_button",
* admin_label = @Translation("Abonneer op Nieuwsbrief"),
* )
*/
class SubscribeFormButton extends BlockBase {
/**
* {@inheritdoc}
*/
public function build() {
$text = '<a href="/multistep-form" class="use-ajax" data-dialog-type="modal">Abonneer</a>';
return [
'#markup' => $text,
'#attached' => array(
'library' => array(
'core/drupal.dialog.ajax',
'core/jquery.form',
),
),
];
}
}
Het formulier in de pop-up ziet er als volgt uit:
Ik heb ook een aangepaste bibliotheek verbonden vanuit het drupalbook.libraries.yml-bestand:
modules/custom/drupalbook/drupalbook.libraries.yml
multistep_form:
css:
css/multistep_form.css: {}
js:
scripts/multistep_form.js: {}
dependencies:
- core/jquery
- core/jquery.once
Het is noodzakelijk om het formulier te stylen en de benodigde jQuery-plug-ins ermee te verbinden. Daarom moeten er meer bestanden worden aangemaakt:
modules/custom/drupalbook/css/multistep_form.css
modules/custom/drupalbook/scripts/multistep_form.js
Voorbeelden van de code kunnen worden gevonden op github:
https://github.com/levmyshkin/drupalbook8