Problem/Motivation
I have a multi page webform that can be saved as Draft. On this webform i have Likert form elements with 0 value for the first answer. When i continue this form the radio boxes will be prefilled on each page, but normally nothing should be prefilled(if there are no default values) no matter if this is a new submission or an existing one.
Steps to reproduce
- Create a webform with a Likert form element where you have a answer with 0 value.
- Enter that form and save it as Draft.(Idk if this can be done from UI or it has to be done programmatically.)
- Continue that draft form.
- You see that all radio boxes that have 0 value is ticked.
Proposed resolution
Because this is a Drupal core bug that https://www.drupal.org/project/drupal/issues/1381140 caused and hasn't been solved yet, for the time being it is better to solve this in the Webform module with a patch. I created this patch.
Reason(generated with AI):
There are long‑standing Drupal core issues about radios being incorrectly checked when the value is an empty string and the option value is "0". However, there is no merged core change that alters the current Radio::preRenderRadio() behavior. The common resolution is to work around it at the form element level (exactly what we implemented in WebformLikert).
Relevant core issues
- "#type 'radio' ... with key '0' always is 'checked'..." — Drupal core issue 2493843 (discusses the empty()-based check and unintended checking of the '0' option). https://www.drupal.org/project/drupal/issues/2493843
- "A #default_value = 0 for #type radios checks all radios" — Drupal core issue 1381140 (similar root cause with loose/empty matching semantics). https://www.drupal.org/project/drupal/issues/1381140
- Core implementation reference (current behavior): Radio::preRenderRadio() uses an empty() comparison that considers both "" (empty string) and "0" as empty, which leads to the accidental check:
if (isset($element['#return_value']) && $element['#value'] !== FALSE && !is_array($element['#value']) && ((empty($element['#value']) && empty($element['#return_value'])) || (string) $element['#value'] === (string) $element['#return_value'])) { $element['#attributes']['checked'] = 'checked';
Current status and why a patch isn’t in core
- The behavior is deeply tied to historical/BC expectations of how radios treat "empty" values. Attempts to change it risk breaking forms relying on the current semantics.
- As of Drupal 10/11, there hasn’t been a merged core change to remove the empty() check or to special‑case "" vs "0".
Remaining tasks
User interface changes
API changes
Data model changes
| Comment | File | Size | Author |
|---|---|---|---|
| #7 | webform-likert-prefilled-3604225-7.patch | 1.29 KB | mibfire |
Comments
Comment #2
mibfire commentedComment #3
mibfire commentedComment #4
mibfire commentedI have created a patch to fix this issue.
Comment #5
liam morlandThanks for the patch. Fixes need to be against 6.3.x first. There needs to be a merge request and it should have tests.
Comment #6
mibfire commentedHi @liam morland
Thanks for the heads up.
Comment #7
mibfire commentedI made mistake in filename of patch. I fixed it.