I just had a read through the code of the Select FormElement in the Drupal core, and it appears to me that you cannot use the "#default_value" key to, well, assign a default value to the element
The #default_value option is used in two occasions in the code:
1) to check whether or not an "empty option" should be inserted, in the processSelect method
2) to set a default value for a MULTIPLE select.
The default value is never used for a single select, which to me makes no sense; if there is a default value set, that option should be selected by default, and there should be no 'empty option'.
Am I crazy, or am I onto something here?
API reference to check the source code:
https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Render%21...
| Comment | File | Size | Author |
|---|---|---|---|
| #12 | Screenshot 2025-09-30 at 6.59.50 PM.png | 370.12 KB | mohit_aghera |
Issue fork drupal-2895887
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
- 2895887-select-form-element
changes, plain diff MR !5706
Comments
Comment #3
pameeela commentedHave discussed with @quietone and we decided to close this because the default value for single selects appears to work fine. There are no specifics on how to reproduce the issue described, it's more of a question about the code, but it appears to work as expected.
If anyone has further info on how to reproduce this issue, please provide complete steps to reproduce the issue (starting from "Install Drupal core") in the issue summary and set the issue status back to "Active".
Comment #4
sagesolutions commentedI've also came across this scenario and found what works (and what doesn't). I'm currently on Drupal 10.0.3 and PHP 8.1
I needed to create a block with a form that submits to an external url. Its a simple form and only has a select box and submit button.
In the build() function of my block, I added the following:
The select box renders properly, but the default value is not set.
So, instead I thought to create a Form and then load the form into the block and see if that works. And it did!
So I created the form class extending FormBase and added the select field to the buildForm() method
And then in my block, I embedded the form via
Calling the form this way set the default value on the select field.
Comment #5
phjouSame issue here,
If you create a renderable array of a select and use the render service to render it, you will get the select but default_value is just ignored. It definitely doesn't make sense. It should work in both context, when used in a proper drupal form (works already) but also if you render an isolated select.
Comment #6
johan.gant commentedI've been scratching my head about this for a while today. I have a views exposed form element as a select element, with about 10 options and should only take one value. I can use #value to pre-populate the initial value but this is then fixed and can't be changed by the user. If I try to use #default_value to indicate a starting value/pre-selection it's completely ignored on this element type.
I'm pretty sure I've used #default_value as an attribute in Drupal 7 and 8. The Select.php class docs state:
If I try to adjust #empty_value the form tells me 'The submitted value is not allowed'.
Entirely probable that I'm applying the wrong combination of properties (somehow) but I'm confused how #default_value can't be applied on this element (string for single value, array for multiple values), when other elements accept this property in a consistent manner.
What can be done to clarify the appropriate way to use the Select element via the class docs, or is this a bug?
Comment #7
akhil babuI was able to reproduce this issue.
If I create a form with a select field and use \Drupal::formBuilder()->getForm() to render the form and return it from a controller, then the default value of the select element gets applied.
But if I do this in controller
Then the element gets rendered, but default value is ignored.
Options in the select element are processed by form_select_options function.
Every option in the select element will have a 'selected' attribute. This attribute should be set to true for the option that is selected as the default value. This is the part of the code that handles this logic.
The '#value' attribute of the element determies if an option should be selected by default or not.
When the form is rendered through form API, \Drupal\Core\Form\FormBuilder::handleInputElement() sets the '#value' attribute to the element. The function goes through several checks to get the #value. If #value is still not set, then #default_value is set as #value.
This entire process is skipped when form is rendered directly using render service. As a result, '#value' is not set and eventually default value is not highlightet in frontend.
form_select_options is called from template_preprocess_select. I have added a check to add '#value' attribute if its not set. This fixes the issue and default value get's selected when element is rendered. But not sure if this is the proper way to address this problem.
Comment #9
johan.gant commentedFor what it's worth, I found that I could work around this with something like:
Which essentially means if there's no query string value for the filter, it sets a default value.
Wouldn't it be a lot handier to just set a #default_value attribute on the render element and internalise any other complications around that to the Select render element class? I appreciate I might not fully understand the existing reasons so would be more than happy if someone who can explain it in more simple terms could do that and enlighten me.
Comment #11
realgiucas commentedIt's a pretty big and annoying bug.
explanations would be appreciated.
Comment #12
mohit_aghera commentedI came across this issue during bugsmash traige.
First, I tried to reproduce issue based on comment #7
My controller's callback has code something like this.
Essentially it returns the form, however I feel this doesn't seem correct way to render the form.

Above approach will render select list, however it won't be the actual form element in dom.
Refer following screenshot.
So I believe we should use the form builder service to build and render the form.
The form builder service also takes care of multiple things like build_id, token etc. to the form.
Later I tried the approach from comment #4
There also rendering form directly in block
however, this also won't render the actual
<form>in DOM and it will just render the select list.I tested that if we use the form builder service and render the form it works fine.
Considering this I think we should close the issue since right way to build renderable form is to run through form builder service.
Please reopen the issue again if you feel I'm missing something in reproducing the issue.
Comment #13
mohit_aghera commentedComment #15
smustgrave commentedSince there's been no follow up going to close this one out.