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.

Comments

tunic created an issue. See original summary.

anweshasinha’s picture

Hi,
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;
}

tunic’s picture

Could 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.

tunic’s picture

Issue summary: View changes
anweshasinha’s picture

StatusFileSize
new814 bytes

Hi,
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.

_utsavsharma’s picture

Status: Active » Needs review
StatusFileSize
new776 bytes
new815 bytes

Fixed failures in #5.

smustgrave’s picture

Status: Needs review » Needs work
Issue tags: +Needs tests

Version: 11.x-dev » main

Drupal core is now using the main branch as the primary development branch. New developments and disruptive changes should now be targeted to the main branch.

Read more in the announcement.