Drupal - Resolve the error "An illegal choice has been detected..."
The problem is most likely because of a requirement for FAPI AJAX which is documented in AJAX Forms in Drupal 7, though can be easily missed.
Changes to the form must only be made in the form builder function (ajax_example_autocheckboxes() in the example here), or validation will fail. The callback function must not alter the form or any other state.
The fact that you're setting the form element [#options]
in the AJAX callback is definitely a problem. The AJAX callback should only return the array or HTML to be printed, not change the form. That callback should only contain the return
statement.
The changes to your form should be made in the form_alter. Also, you should use the form_state array to check whether a value has been selected for your first dropdown. This will be updated during an AJAX request.
I recommend looking at the examples module, as well as these pages for more information on AJAX in FAPI. It can definitely be tricky.
- AJAX Forms in Drupal 7
- AJAX Framework
The below method can be used to neglect errors only for those fields into which value has been added through ajax
As per the code given below you can enter the field element which gives error so that the value changed in the second dropdown due to change in the first dropdown due to the use of ajax will not show an error.
/**
* Custom Form Validation.
* Removes all form validation errors caused by a 'foo][bar' form element.
*/
function my_module_form_validate($form, &$form_state) {
$errors = form_get_errors();
if ($errors) {
// Clear errors.
form_clear_error();
// Clear error messages.
$error_messages = drupal_get_messages('error');
// Initialize an array where removed error messages are stored.
$removed_messages = array();
// Remove all errors originated by the 'foo][bar' element.
foreach ($errors as $name => $error_message) {
if ($name == 'foo][bar') {
$removed_messages[] = $error_message;
unset($errors[$name]);
}
}
// Reinstate remaining errors.
foreach ($errors as $name => $error) {
form_set_error($name, $error);
// form_set_error() calls drupal_set_message(), so we have to filter out
// these from the error messages as well.
$removed_messages[] = $error;
}
// Reinstate remaining error messages (which, at this point, are messages that
// were originated outside of the validation process).
foreach (array_diff($error_messages['error'], $removed_messages) as $message) {
drupal_set_message($message, 'error');
}
}
}