I have an issue with a custom form in Drupal 8, using Ajax.
Let me explain. I have two select fields, and when you choose an option in the first one, an Ajax request will get options for the second one. When you submit the form, it will redirect you to a specific page. All of this works well.
The issue is when you get redirect to a page, and you hit the previous page button of your browser. By default, you get the first option of the first field, and the first option of the second field, but in this specific case, you get the option you previously selected for the first field, but the second select doesn't get the good values, as the Ajax request does not get fired.
Exemple :
When you choose "Option A" in the first field, you get "Value A.1" and "Value A.2" in the second field, if you choose "Option B", you get "Value B.1", etc...
For exemple, if you submit the form with "Option C" and "Value C.3", you get redirected to a page, and if you go back to the previous page in your browser, you'll have "Option C" selected, but with the values of "Option A" in the second field ("Value A.1", "Value A.2", ...), and if you submit, you get this error
An illegal choice has been detected. Please contact the site administrator.
I surely miss something with the rebuild of the form, but I can"t find any solutions.
Here's my code :
<?php
namespace Drupal\chdou_intuitive_search\Form;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Ajax\ReplaceCommand;
/**
* Class DefaultForm.
*
* @package Drupal\chdou_intuitive_search\Form
*/
class DefaultForm extends FormBase {
/**
* {@inheritdoc}
*/
public function getFormId() {
return 'default_form';
}
/**
* {@inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state) {
$form['i_wish'] = [
'#type' => 'select',
'#title' => $this->t('Je souhaite'),
'#options' => [
'appointment' => $this->t('prendre rendez-vous'),
'doctor' => $this->t('rechercher un médecin'),
'help' => $this->t('une aide ou un soutien')
],
'#default_value' => 'appointment',
'#required' => true,
'#multiple' => false,
'#size' => false,
'#ajax' => [
'callback' => '::getOptions',
'event' => 'change',
'wrapper' => 'what',
]
];
$parent = $form_state->getValue('i_wish');
if (empty($parent)) {
$parent = $form['i_wish']['#default_value'];
}
$form['what'] = [
'#prefix' => '<div id="what">',
'#suffix' => '</div>',
'#type' => 'select',
'#title' => $whatLabel,
'#options' => $this->getOptionsBySelection($parent),
'#default_value' => key($this->getOptionsBySelection($parent)),
'#required' => true,
'#multiple' => false,
'#size' => false,
];
$form['submit'] = [
'#prefix' => '<div class="form-actions">',
'#suffix' => '</div>',
'#type' => 'submit',
'#value' => $this->t('Search'),
'#attributes' => [
'class' => [
'button',
],
],
];
return $form;
}
/**
* Ajax callback for the "Je souhaite" dropdown
*/
public function getOptions(array &$form, FormStateInterface $form_state) {
return $form['what'];
}
/**
* Returns list of options that correspond to the "Je souhaite" selected option
*/
public function getOptionsBySelection($parent) {
switch ($parent) {
case 'appointment':
$terms = $this->getAppointmentOptions();
break;
case 'doctor':
$terms = $this->getDoctorOptions();
break;
case 'help':
$terms = array(
'140' => 'Je suis patient',
'141' => 'Je suis aidant',
'142' => 'Pour un proche',
);
break;
default:
break;
}
return $terms;
}
/**
* Returns list of care_sheet_consultation taxonomy tree
*/
public function getAppointmentOptions() {
// ...
}
/**
* Returns list of :
* - care_sheet_consultation
* - care_sheet_hospitalization
* - care_sheet_medical_techno
* taxonomy trees
*/
public function getDoctorOptions() {
// ...
}
/**
* {@inheritdoc}
*/
public function validateForm(array &$form, FormStateInterface $form_state) {
parent::validateForm($form, $form_state);
}
/**
* {@inheritdoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
// CHOIX : Je souhaite prendre rendez-vous
if ($form_state->getValue('i_wish') == 'appointment') {
$form_state->setRedirect('entity.taxonomy_term.canonical', [
'taxonomy_term' => $form_state->getValue('what')
]);
}
// CHOIX : Je souhaite rechercher un médecin
else if ($form_state->getValue('i_wish') == 'doctor') {
$form_state->setRedirect('entity.node.canonical', [
'node' => '29', // i.e. page Annuaire
'service' => $form_state->getValue('what')
]);
}
// CHOIX : Je souhaite une aide ou un soutien
else if ($form_state->getValue('i_wish') == 'help') {
$form_state->setRedirect('entity.node.canonical', [
'node' => $form_state->getValue('what')
]);
}
}
}