Form element "checkboxes" with "required" fails validation if all selected options are disabled

Created on 30 June 2022, about 3 years ago
Updated 30 January 2023, over 2 years ago

Problem/Motivation

Form element "checkboxes" with "required" fails the $is_empty_value validation, if all selected options are disabled.

Steps to reproduce

1. Get the default Drupal instance with "Article" node bundle and field_tags field.
Create two tags (Tag1, Tag2), create an article and add the "Tag1" to it (only one tag).

2. Mark the field_tags field as "required" in field settings.

3. Change for the field_tags field the widget type to "Check boxes/radio buttons".

4. Open the Article edit form, see that the "Tag1" checkbox is checked. Submit the form - it should be submitted successfully.

5. Make the "Tag1" checkbox disabled in the Article edit form via custom hook:

function my_module_form_alter(&$form, FormStateInterface $form_state, $form_id) {
  if($form_id !== 'node_article_edit_form') {
    return;
  }
  $form['field_tags']['widget'][1]['#disabled'] = TRUE;
}

6. Open the Article edit form again. See the "Tag1" checkbox checked and disabled.

7. Press the "Save" button and see the error message "Tags field is required".
But the "Tag1" value is selected (regardless of disabled status), so the field is not empty!

8. Check the non-disabled "Tag2" checkbox and save - validation should be passed well.

So in the step 7 - Drupal shouldn't show the required error, because the "Tag1" value is selected, regardless of disabled status.

Proposed resolution

In the function Drupal\Core\Render\Element\Checkboxes::valueCallback() fill actual values from default values even if the user input is empty:

    else {
      $value = [];

      // Because the disabled checkboxes don't receive their input from the
      // form submission, we should fill their default value.
      if (!empty($element['#default_value'])) {
        foreach ($element['#default_value'] as $key) {
          if (!empty($element[$key]['#disabled'])) {
            $value[$key] = $key;
          }
        }
      }
      
      return $value;
    }

Remaining tasks

User interface changes

API changes

Data model changes

Release notes snippet

πŸ› Bug report
Status

Needs review

Version

10.1 ✨

Component
FormΒ  β†’

Last updated about 8 hours ago

Created by

πŸ‡¦πŸ‡²Armenia murz Yerevan, Armenia

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

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

  • πŸ‡ͺπŸ‡ΈSpain ady1503

    Hello.

    I'm asking for the community's help again because I think there is a bug in drupal core with the form #state API.

    Specifically, checkboxes and lists are not activated as required by form #state.

    In the case of checkboxes, the requirement asterisk is not added, but required="required" and aria-required="true" attribute are added, but the checkboxes do not become required.

    The same is with the lists except that the asterisk is added, but it is not required either.

    I have a list, which I use with the checkbox/radio widget, which is the master.

    And I also use the other slave list with the checkbox/radio widget, I have controlled the visibility and the requirement with form #state.

    When I choose a value or checkbox from the master list the slave list becomes visible and should be and required.

    And the requirement doesn't work, an visibility working well.

    I read a lot about this bug, since the drupal 7 version it is not well fixed.

    If someone can give me some solution.

    Thanks for help.

    /**
     * Implements hook_form_BASE_FORM_ID_alter() for node form.
     */
    function buangh_mantenimiento_diario_piscina_form_node_form_alter(&$form, FormStateInterface $form_state, $form_id): void {
      $node = $form_state->getFormObject()->getEntity();
      if ($node->getType() !== 'mantenimiento_diario_piscina') {
        return;
      }
    
    // field hide/view
    $form['field_operacion_filtro_mantenimi']['#states'] = [
      'visible' => [
        ':input[name^="field_operacion_de_mantenimiento[Limpieza del filtro]"]' => ['checked' => TRUE],
      ],
    ];
    // field required
    $form['field_operacion_filtro_mantenimi']['widget']['#states'] = [
      'required' => [
        ':input[name^="field_operacion_de_mantenimiento[Limpieza del filtro]"]' => ['checked' => TRUE],
      ],
    ];
    
    }
  • πŸ‡ΊπŸ‡ΈUnited States smustgrave

    Did you try the patch on this ticket?

  • Status changed to Needs work over 2 years ago
  • πŸ‡ΊπŸ‡ΈUnited States smustgrave

    For #26.

    To see if a better solution can be had.

  • πŸ‡΅πŸ‡±Poland dmitry.korhov Poland, Warsaw

    rebased for 10.1.1

  • πŸ‡¬πŸ‡§United Kingdom joachim

    Re #26, this doesn't seem to be a problem at the checkbox level. This form works and passes validation:

        $form['test-3293609'] = [
          '#type' => 'checkbox',
          '#title' => 'test 3293609',
          '#default_value' => TRUE,
          '#disabled' => TRUE,
          '#required' => TRUE,
        ];
    
        $form['submit'] = [
          '#type' => 'submit',
          '#value' => $this->t('Submit'),
        ];
    

    This one with a checkboxes element fails validation:

        $form['test-3293609'] = [
          '#type' => 'checkboxes',
          '#title' => 'test 3293609',
          '#options' => [
            'alpha' => 'Alpha',
            'beta' => 'Beta',
          ],
          '#default_value' => [
            'alpha' => 'alpha',
          ],
          '#required' => TRUE,
        ];
        $form['test-3293609']['alpha']['#disabled'] = TRUE;
    
        $form['submit'] = [
          '#type' => 'submit',
          '#value' => $this->t('Submit'),
        ];
    
Production build 0.71.5 2024