With Drupal 9 we have access to the class confirmFormBase which extends FormBase. This class is used to quickly add a confirm step to your form. Common usage is to confirm a deletion: "Are you sure you want to delete node 23?"
The basic usage is to create a new route for the confirm form, living side of your form, and use route parameter to pass an id.
One form with confirm step included
But here we want to have a single form for the building, submit and confirmation, this usage is used once in Drupal core is for the configuration single import class: ConfigSingleImportForm.php.
The trick is to have a class extending confirmFormBase and implementing methods for formBase from formInterface :
public function getFormId();
public function buildForm(array $form, FormStateInterface $form_state);
public function submitForm(array &$form, FormStateInterface $form_state);
// Si besoin d'une validation.
public function validateForm(array &$form, FormStateInterface $form_state);
And from confirmFormInterface
public function getQuestion();
public function getCancelUrl();
Next step is to add a variable to store our value. It could be a string, an id or an array> for more complex values:
protected $action = NULL;
The most important part is to add a condition to submitForm()
to avoid submission at first and store the form value concerned in our varibale:
public function submitForm(array &$form, FormStateInterface $form_state): void {
if (!$this->action) {
$form_state->setRebuild();
$this->action = $form_state->getValue('action');
return;
}
// Our submit code.
}
Then we need a condition on buildForm()
to build either our form or the confirm form if our variable is filled :
public function buildForm(array $form, FormStateInterface $form_state): array {
if ($this->action) {
return parent::buildForm($form, $form_state);
}
// Our $form array with submit.
}
If the form include a validation with validateForm()
, we need to skip validation for the confirm form:
public function validateForm(array &$form, FormStateInterface $form_state): void {
if ($this->action) {
return;
}
// Notre code de validation.
}
Full example of a form
Here is a full example for this one form class:
demo_confirm_form.routing.yml
Sample of a minimum form class: web/modules/demo_confirm_form/src/Form/ExampleMinimalForm.php
A more advanced class with 2 values to store for confirmation: web/modules/demo_confirm_form/src/Form/ExampleForm.php