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

Comments

mibfire created an issue. See original summary.

mibfire’s picture

Title: Linket radio boxes are prefilled on draft form » Likert radio boxes are prefilled on draft form
mibfire’s picture

Issue summary: View changes
mibfire’s picture

StatusFileSize
new1.29 KB

I have created a patch to fix this issue.

liam morland’s picture

Version: 6.2.10 » 6.3.x-dev
Status: Active » Needs work
Issue tags: +Needs merge request, +Needs tests

Thanks for the patch. Fixes need to be against 6.3.x first. There needs to be a merge request and it should have tests.

mibfire’s picture

Hi @liam morland

Thanks for the heads up.

mibfire’s picture

StatusFileSize
new1.29 KB

I made mistake in filename of patch. I fixed it.