Problem/Motivation
This comes from #3361695: Fix the documentation for #empty_value on Drupal\Core\Render\Element\Select and #1936636: Fix the documentation for #empty_value.
In form API, when the value of the property #empty_option is also present in #options array as a key, the value of #options for that key can be replaced by the value of the property #empty_value.
See the following explanation for details on how this happens: https://www.drupal.org/project/documentation/issues/1936636#comment-1505...
Steps to reproduce
Declare a form with the following element:
$element =
'#type' => 'select',
'#options' => [
0 => 'zero',
1 => 'one',
2 => 'two'
],
'#required' => TRUE,
'#empty_value' => TRUE,
'#empty_option' => "Some empty value"
When the form is rendered it will show three options:
"Some empty value", "one" and "two"
Instead of four:
"Some empty value", "zero", "one" and "two"
Proposed resolution
Detect this condition and raise an error or warning.
Assert was proposed, but as said in previous issues: "assert will only work when assertions are enabled. This can be the case for automatic testing but it is not on production environments. Given the dynamic nature of forms, it is possible that the case where #options is overriden only happens on certain situations".
Triggering and exception could be too drastic. Adding a warning will alert any developer debugging a form impacted by this condition.
If an error is preferred I would think on adding a try-catch at the form builder level to catch this error and other errors on the form, but that would be another task much bigger than this one.
Displaying a Drupal error or warning message could another option. The select element could detect the condition and raise the message.
Remaining tasks
Decide what to raise (exception, warning, assert, drupal message or another solution).
User interface changes
None.
API changes
None.
Data model changes
None
Release notes snippet
Not needed.
| Comment | File | Size | Author |
|---|---|---|---|
| #6 | 3375072-6.patch | 815 bytes | _utsavsharma |
| #6 | interdiff_5-6.txt | 776 bytes | _utsavsharma |
| #5 | 3375072_5.patch | 814 bytes | anweshasinha |
Comments
Comment #2
anweshasinha commentedHi,
We can add '#description' property as condition if we have '#empty_option' property in the form. This will conditionally render the description below the form field. Refer the example given below:-
/**
* {@inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state): array {
$form['select_element'] = [
'#type' => 'select',
'#options' => [
0 => 'zero',
1 => 'one',
2 => 'two'
],
'#required' => TRUE,
'#empty_value' => TRUE,
'#empty_option' => "Some empty value"
];
if($form['select_element']['#empty_option']) {
$form['select_element']['#description'] = 'Empty option present will replace the option.';
}
$form['actions'] = [
'#type' => 'actions',
'submit' => [
'#type' => 'submit',
'#value' => $this->t('Send'),
],
];
return $form;
}
Comment #3
tunicCould be an option to solve this but it has to be implemented on the element level. However, adding a text to the description could be not enough (maybe the text is hidden and devs won't see it). I would say to set a drupal warning message instead.
Comment #4
tunicComment #5
anweshasinha commentedHi,
I have created a patch which displays a warning, when $form['#empty_value'] exist in the form and is set to 1 as I saw that the $form['#empty_option'] replaces the $form['#option'] only when $form['#empty_value'] is set to 1. Please review the patch.
Comment #6
_utsavsharma commentedFixed failures in #5.
Comment #7
smustgrave commented