Select form element misses the "- Select -" option if marked as not required

Created on 8 May 2025, about 1 month ago

Problem/Motivation

I need to make the "- Select -" option available by default for non-required fields in a Drupal Form. But can't do this for some reason, seems this is a bug in the Drupal Form API.

Steps to reproduce

1. Create a Drupal form like this:

  public function buildForm(array $form, FormStateInterface $form_state) {
    $form['val1'] = [
      '#title' => 'Val1',
      '#type' => 'select',
      '#options' => ['one', 'two', 'three'],
      '#required' => TRUE,
    ];
    $form['val2'] = [
      '#title' => 'Val2',
      '#type' => 'select',
      '#options' => ['one', 'two', 'three'],
      '#required' => FALSE,
    ];
    return $form;

2. See that the "- Select -" option is available for the required field "Val1"
But not available for the non-required field "Val2":

Proposed resolution

I see no real reasons for this strange behavior, even the opposite - for the non-required fields we should provide the ability to select "nothing".

So, looks like we should find the source of this strange behavior, and provide a fix for it.

Remaining tasks

User interface changes

Introduced terminology

API changes

Data model changes

Release notes snippet

🐛 Bug report
Status

Active

Version

11.0 🔥

Component

forms system

Created by

🇦🇲Armenia murz Yerevan, Armenia

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

  • Issue created by @murz
  • I think the setting you are looking for is #empty_value.

    Its documentation reads:

     * - #empty_option: (optional) The label to show for the first default option.
     *   By default, the label is automatically set to "- Select -" for a required
     *   field and "- None -" for an optional field.
     * - #empty_value: (optional) The value for the first default option, which is
     *   used to determine whether the user submitted a value or not.
     *   - If #required is TRUE, this defaults to '' (an empty string).
     *   - If #required is not TRUE and this value isn't set, then no extra option
     *     is added to the select control, leaving the control in a slightly
     *     illogical state, because there's no way for the user to select nothing,
     *     since all user agents automatically preselect the first available
     *     option. But people are used to this being the behavior of select
     *     controls.
    
  • There is a @todo below that documentation saying "address the above issue in Drupal 8", so I guess that hasn't yet happened. I hope there is an issue open somewhere to make this "just work" by default.

  • I am relating a few issues.

Production build 0.71.5 2024