Problem/Motivation

I tried to identify if a checkbox / radio is part of checkboxes / radios. For proper form theming I require to add a CSS class to single form elements that are of type checkbox / radio, but not if these checkbox / radio is part of a group of checkboxes / radios.

After long debugging I found \Drupal\Core\Render\Element\Checkboxes class, but it is far away from doing something reliable for this themers situation. My findings have shown that there are no good keys in checkbox/radio render arrays that indicate if the element is a checkbox / radio of checkboxes / radios - except abusing some other keys like:

  1. #error_no_message = TRUE
  2. #weight =
    • data type integer (value = 0) - if a single checkbox
    • data type float (value = 0.001+) - if multiple checkboxes

Proposed resolution

Add key '#is_group_of_elements' = TRUE to the element to indicate that a checkbox/radio is part of a checkboxes/radios group.

Remaining tasks

Patch
Review
Commit

User interface changes

None

API changes

No breaking change, just an addition.

Data model changes

None.

Comments

hass created an issue. See original summary.

hass’s picture

Issue summary: View changes
hass’s picture

Issue summary: View changes
hass’s picture

Issue summary: View changes
hass’s picture

Status: Active » Needs review
StatusFileSize
new1.65 KB
hass’s picture

StatusFileSize
new1.64 KB

Fixed radio documentation.

hass’s picture

I'm not sure if this is the best idea. I tried getting an idea what #parent is, but failed. I would much more prefer to see the checkboxes element go into #parent what gives us more flexibility.

But as I have not found a single example how #partent is used in render arrays this requires some help how to proceed.

Version: 8.0.x-dev » 8.1.x-dev

Drupal 8.0.6 was released on April 6 and is the final bugfix release for the Drupal 8.0.x series. Drupal 8.0.x will not receive any further development aside from security fixes. Drupal 8.1.0-rc1 is now available and sites should prepare to update to 8.1.0.

Bug reports should be targeted against the 8.1.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.2.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.1.x-dev » 8.2.x-dev

Drupal 8.1.9 was released on September 7 and is the final bugfix release for the Drupal 8.1.x series. Drupal 8.1.x will not receive any further development aside from security fixes. Drupal 8.2.0-rc1 is now available and sites should prepare to upgrade to 8.2.0.

Bug reports should be targeted against the 8.2.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.3.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.2.x-dev » 8.3.x-dev

Drupal 8.2.6 was released on February 1, 2017 and is the final full bugfix release for the Drupal 8.2.x series. Drupal 8.2.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.3.0 on April 5, 2017. (Drupal 8.3.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.3.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.3.x-dev » 8.4.x-dev

Drupal 8.3.6 was released on August 2, 2017 and is the final full bugfix release for the Drupal 8.3.x series. Drupal 8.3.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.4.0 on October 4, 2017. (Drupal 8.4.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.4.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.4 was released on January 3, 2018 and is the final full bugfix release for the Drupal 8.4.x series. Drupal 8.4.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.5.0 on March 7, 2018. (Drupal 8.5.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.5.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.6 was released on August 1, 2018 and is the final bugfix release for the Drupal 8.5.x series. Drupal 8.5.x will not receive any further development aside from security fixes. Sites should prepare to update to 8.6.0 on September 5, 2018. (Drupal 8.6.0-rc1 is available for testing.)

Bug reports should be targeted against the 8.6.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.6.x-dev » 8.8.x-dev

Drupal 8.6.x will not receive any further development aside from security fixes. Bug reports should be targeted against the 8.8.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.9.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.7 was released on June 3, 2020 and is the final full bugfix release for the Drupal 8.8.x series. Drupal 8.8.x will not receive any further development aside from security fixes. Sites should prepare to update to Drupal 8.9.0 or Drupal 9.0.0 for ongoing support.

Bug reports should be targeted against the 8.9.x-dev branch from now on, and new development or disruptive changes should be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

kristen pol’s picture

Version: 8.9.x-dev » 9.1.x-dev
Status: Needs review » Needs work
Issue tags: +Bug Smash Initiative, +Needs reroll

Doesn't apply to 9.1.x so needs reroll.

hardik_patel_12’s picture

Status: Needs work » Needs review
Issue tags: -Needs reroll
StatusFileSize
new1.51 KB

Re-rolled against 9.1.x. Kindly review a patch.

kristen pol’s picture

Issue tags: +Needs tests

Thanks for the update.

1) Not sure this would be considered a bug but leaving for now.

2) This would need tests so tagging.

3) Not sure how this could be manually tested without custom code.

4) Looking at other '#is_' usage in core and see:

  • #is_button
  • #is_weight
  • #is_multiple

Given that, assuming this approach might be accepted, it might be better to shorten the text though maybe "#is_group" is too ambiguous and/or hard to differentiate from #is_multiple.

kristen pol’s picture

Status: Needs review » Needs work

Moving back to "Needs work" for tests.

Version: 9.1.x-dev » 9.2.x-dev

Drupal 9.1.0-alpha1 will be released the week of October 19, 2020, which means new developments and disruptive changes should now be targeted for the 9.2.x-dev branch. For more information see the Drupal 9 minor version schedule and the Allowed changes during the Drupal 9 release cycle.

mohit_aghera’s picture

Status: Needs work » Needs review
StatusFileSize
new3.31 KB
new1.8 KB

Adding a few Kernel test cases to check if the field attribute is present or not.
I'm not quite sure about this approach. Feel free to suggest better approaches to implement test cases related to this.

Another one that I am thinking of:
- Create one form
- invoking one template_preprocess_hook
- Set the state variable inside template preprocess hook based on "#is_group_of_elements"
- Again assert the state variable and ensure that it is true.

kristen pol’s picture

Issue tags: -Needs tests

Thanks for the tests! Noticed something trivial but otherwise it seems clear to me. Tests pass. Let me see if anyone in bugsmash has thoughts on the naming convention.

+++ b/core/tests/Drupal/KernelTests/Core/Element/FormElementPropertiesTest.php
@@ -0,0 +1,44 @@
+      '#title' => 'Test',

Extreme Nitpick: Could be 'Test Checkboxes' since other one is 'Test Radios'.

guilhermevp’s picture

StatusFileSize
new688 bytes
new3.33 KB

Small update in patch 20 just addressing comment #22 suggestion.

kristen pol’s picture

Thank you for the wording change. That looks good. I'll double check again to see if anyone in bugsmash has thoughts on the is_group_of_elements naming.

kristen pol’s picture

Category: Bug report » Task

After discussing with the bugsmash team, moving this to a task. But, leaving the Bug Smash Initiative tag since we worked on this issue as part of the initiative.

quietone’s picture

Status: Needs review » Needs work

I was asked by mohit_aghera for a review. This is likely the first time I have reviewed an issue about a form element.

Starting with the issue summary. That gave me an understanding of the problem so far so good.

Now reading the issue. In #7 the solution used here is questioned and help for a better solution was asked for. The following comments do not address that question. I don't know enough about forms to know if there is a better way to solve this. Can someone confirm?

Like Kristen Pol I think 'is_group_of_elements' a big long and prefer 'is_group'. Personally, I would not confuse that with 'is_multiple' another option could be 'is_group_member'. That makes more sense to me because an element is not a group of elements.

Now looking at the patch.

  1. +++ b/core/lib/Drupal/Core/Render/Element/Checkboxes.php
    @@ -84,6 +84,10 @@ public static function processCheckboxes(&$element, FormStateInterface $form_sta
    +          '#is_group_of_elements' => TRUE,
    
    +++ b/core/lib/Drupal/Core/Render/Element/Radios.php
    @@ -81,6 +81,10 @@ public static function processRadios(&$element, FormStateInterface $form_state,
    +          '#is_group_of_elements' => TRUE,
    

    This is setting the default to be TRUE? How does one make it FALSE?

  2. +++ b/core/lib/Drupal/Core/Render/Element/Checkboxes.php
    @@ -84,6 +84,10 @@ public static function processCheckboxes(&$element, FormStateInterface $form_sta
    +          // Indicate that this checkbox is part of a group of checkboxes.
    +          // Themers should be able to use this value in hook_preprocess_HOOK()
    +          // to apply conditional theming.
    
    +++ b/core/lib/Drupal/Core/Render/Element/Radios.php
    @@ -81,6 +81,10 @@ public static function processRadios(&$element, FormStateInterface $form_state,
    +          // Indicate that this radio is part of a group of radios.
    +          // Themers should be able to use this value in hook_preprocess_HOOK()
    +          // to apply conditional theming.
    

Explaining the purpose of the property should be in FormElement. Here, tell the user why it is set to TRUE.

The new property should be documented in \Drupal\Core\Render\Element\FormElement. Looking at the file it would be something like
"(bool) TRUE if this element is part of a group of checkboxes or radios. FALSE otherwise. This allows themers to to apply conditional theming." That is not meant to be copy/pasted. But it raises another question. Does it matter that this property is only applicable to Checkboxes and Radios?

Next I looked at the test. The test should also test the case when is_group_of_elements is FALSE as well.

And back to the IS. The proposed resolution is not the same as what is implemented, so it needs updating.

I hope that is useful.

quietone’s picture

I think I found a duplicate of this #1612596: Support css class per radio item. It is too late for me to read it thoroughly, so noting it here for now.

mohit_aghera’s picture

Status: Needs work » Needs review
StatusFileSize
new4.45 KB
new3.67 KB

For Suggestion #1
I am not sure if we need to set it FALSE or not.
Reason is, we are setting is_group_of_elements to TRUE for checkboxes and radios element only.
Let me know your thoughts on this.

Suggestion #2
I've updated the comments, so current patches addresses that issue.
Feel free to review the wordings.

Added property in the FormElement class' comments. I've added another test case for single checkbox as well to ensure that property doesn't exist for single checkboxes.

mohit_aghera’s picture

Issue summary: View changes

Updating issue summary.

Version: 9.2.x-dev » 9.3.x-dev

Drupal 9.2.0-alpha1 will be released the week of May 3, 2021, which means new developments and disruptive changes should now be targeted for the 9.3.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

quietone’s picture

Title: Difficult to identify if checkbox / radio is in group of checkboxes / radios in hook_preprocess_input » Add property to identify if checkbox/radio is in group of checkboxes/radios
Issue summary: View changes
Status: Needs review » Needs work

Having another look. Nice to see the additional test case.

  1. +++ b/core/lib/Drupal/Core/Render/Element/FormElement.php
    @@ -80,6 +80,9 @@
    + * - #is_group_of_elements: (bool) It is true, if element is part of a group of
    

    A few lines above this is the descriptions for another boolean, #tree, let's use the same format (bool) TRUE if .... ; FALSE if the values should be flat..

  2. +++ b/core/tests/Drupal/KernelTests/Core/Element/FormElementPropertiesTest.php
    @@ -0,0 +1,56 @@
    +      '#options' => ['SAT' => t('SAT'), 'ACT' => t('ACT')],
    

    The use of t() can be remove throughout the test. Tests should only use the t() function when specifically testing translations.

    I also think the test can be simplified by creating all the fields on one form and then testing that form.

Updated the IS to fix typos and simplify the proposed resolution.

ravi.shankar’s picture

StatusFileSize
new4.43 KB
new1.95 KB

Tried to address point 1 and 2 of comment #31.

quietone’s picture

mohit_aghera’s picture

Status: Needs work » Needs review
quietone’s picture

Status: Needs review » Needs work

@mohit_aghera, thanks for the answers in #28. Thanks resolves my questions.
@ravi.shankar, thanks for the fixes for #31 1 and 2. I think you missed the paragraph about changing the test?

#26
paragraph 3. The question about the approach being used here needs to be resolved. Or maybe I just do not understand because I don't know much about forms.
paragraph 4. Both Kristen Pol and I think that the property name is too long. See #24 and #26
#31 The test can be simplified.

A few code comments.

  1. +++ b/core/lib/Drupal/Core/Render/Element/Checkboxes.php
    @@ -84,6 +84,9 @@ public static function processCheckboxes(&$element, FormStateInterface $form_sta
    +          // Set to true, to indicate that this checkbox is part of a group of
    +          // checkboxes.
    

    See my comment about this comment in Radios.php

  2. +++ b/core/lib/Drupal/Core/Render/Element/FormElement.php
    @@ -80,6 +80,9 @@
    + * - #is_group_of_elements: (bool) TRUE if element is part of a group of
    

    s/if element/if the element/

  3. +++ b/core/lib/Drupal/Core/Render/Element/Radios.php
    @@ -81,6 +81,9 @@ public static function processRadios(&$element, FormStateInterface $form_state,
    +          // Set to true, to indicate that this checkbox is part of a group of
    +          // checkboxes.
    

    This comment is the Radios file so should not be referring to checkboxes. And now that I see this shorted version I think we can get it on one line. As a suggestion,
    "// Indicates this is part of a group." Change that if you like.

  4. +++ b/core/tests/Drupal/KernelTests/Core/Element/FormElementPropertiesTest.php
    @@ -0,0 +1,56 @@
    +class FormElementPropertiesTest extends KernelTestBase {
    

    The title here suggests that this is testing all Form Element properties. It needs a new name. Maybe, RadioCheckboxGroupPropertyTest ? And the test can be simplified, there is no need to create two forms.

quietone’s picture

mohit_aghera asked for some clarification of the second paragraph in #35 in #bugsmash. Ah, I see that is poorly formatted as well. There are two parts. The first, in #7 hass said they were not sure that the approach taken in the patch was the 'right' one and talked about looking at #parent. And, as far as I can tell, that approach has been used in the following patches without question. So, is there a better way to do this? I don't know - I just want to make sure that someone has thought about it. And the second, is questing the name of the new property.

And that ping in #bugsmash was timely as well. I was wondering the other day about #26.2 and didn't manage to get back here to check. In that comment I said I thought the documentation for the new property should be in FormElement and now I think that is wrong. Other elements, such as Url and Weight define properties that are unique to those elements. I now think the documentation for the new element should be in Radios and Checkboxes. If you agree, sorry about the extra work.

Hope that helps.

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.0-rc1 was released on November 26, 2021, which means new developments and disruptive changes should now be targeted for the 9.4.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

jwilson3’s picture

Hit this issue this week #3276250: Gin theme checkbox styles breaks Webform custom composite fields required. Gin theme has some fancy CSS to avoid theming checkboxes incorrectly that would be greatly simplified by this fix getting into core. Thanks for the work that was done on this last year. I guess its not super clear what is being asked to change to take this forward.

andregp’s picture

I'm working on #35 and #36 I'll send a patch in a few moments.

andregp’s picture

Status: Needs work » Needs review
StatusFileSize
new4.36 KB
new7.34 KB

Regarding #35
i - Done. Shortened property name to #is_group_member
1 & 3 - Done! Shortened comments to a single line.
2 - Done.
4 - Done. Renamed test to CheckboxRadioGroupPropertyTest and simplified test to use a single form. I also added one more test case for the single radio case.

Regarding #36
I moved the new property description to Checkbox.php and Radios.php

Status: Needs review » Needs work

The last submitted patch, 40: 2643012-40.patch, failed testing. View results

andregp’s picture

Status: Needs work » Needs review

The fail seems unrelated, requeueing test.

joshua1234511’s picture

Status: Needs review » Reviewed & tested by the community

Tested the patch from #40
All suggestions are rectified in the latest patch
Steps followed.
Added a custom form

$form['options'] = array(
    '#type' => 'checkboxes',
    '#title' => t('Various Options by Checkbox'),
    '#options' => array(
      'key1' => t('Option One'),
      'key2' => t('Option Two'),
      'key3' => t('Option Three'),
    ),
   );
$form['options'] = array(
    '#type' => 'checkboxes',
    '#title' => t('Various Options by Checkbox'),
    '#is_group_member' => FALSE,
    '#options' => array(
      'key1' => t('Option One'),
      'key2' => t('Option Two'),
      'key3' => t('Option Three'),
    ),
   );

Added custom class in preprocess hook using the variable is_group_member
Patch works correctly.

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.0-alpha1 was released on May 6, 2022, which means new developments and disruptive changes should now be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 40: 2643012-40.patch, failed testing. View results

andregp’s picture

Status: Needs work » Reviewed & tested by the community

Unrelated test fail, re-queueing tests and restoring status

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 40: 2643012-40.patch, failed testing. View results

andregp’s picture

Status: Needs work » Reviewed & tested by the community

Unrelated test fail. Restoring status.

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 40: 2643012-40.patch, failed testing. View results

andregp’s picture

Status: Needs work » Reviewed & tested by the community

Unrelated test fail. Restoring status.

joshua1234511’s picture

Tested the patch from #40
Against latest 9.5.x-dev
Patch cleanly apply and works correctly.

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 40: 2643012-40.patch, failed testing. View results

kristen pol’s picture

Status: Needs work » Reviewed & tested by the community

Unrelated test fail. Restoring status.

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 40: 2643012-40.patch, failed testing. View results

Version: 9.5.x-dev » 10.1.x-dev

Drupal 9.5.0-beta2 and Drupal 10.0.0-beta2 were released on September 29, 2022, which means new developments and disruptive changes should now be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 10.1.x-dev » 11.x-dev

Drupal core is moving towards using a “main” branch. As an interim step, a new 11.x branch has been opened, as Drupal.org infrastructure cannot currently fully support a branch named main. New developments and disruptive changes should now be targeted for the 11.x branch, which currently accepts only minor-version allowed changes. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 11.x-dev » main

Drupal core is now using the main branch as the primary development branch. New developments and disruptive changes should now be targeted to the main branch.

Read more in the announcement.