- π¬π§United Kingdom kalpaitch
Following on from @codebymikey's point #29 I've also identified this happens to the 'container' element too, (albeit with the caveat that the container element does not support the #description attribute):
$form['element'] = [ '#type' => 'container', '#description' => 'A description added to the container.' ];
This will result in a container wrapper being rendered with an incorrect 'aria-describedby' attribute.
Following on from @andrewmacpherson's comment #22, I agree there needs to be a more extensible way to declare a form element as a composite form element. But there are also needs to be some consideration for other render elements which get the 'aria-describedby' attribute added.
- π¨π¦Canada Liam Morland Ontario, CA π¨π¦
Liam Morland β made their first commit to this issueβs fork.
- Merge request !7117Issue #2839344: Broken aria-describedby in radios and checkboxes β (Open) created by Liam Morland
- π¨π¦Canada Liam Morland Ontario, CA π¨π¦
I have made a merge request with patch 17 rebased onto 11.x.
I agree with #25, that we should use something more extensible. However, I don't think either of the suggestions is enough information for making it work. The issue is in the
FormBuilder
class, and at that point, you don't have instances ofElementInterface
, you have a render array. So you can't do aninstanceof
test.It might be easier to add an attribute
#is_composite
to the render array?Or if I'm wrong, then I would say it's probably better to have
CompositeFormElementInterface
, because there is also aCompositeFormElementTrait
. So you could even putisComposite
in the trait, and it would be added to any contrib/custom classes using the trait as well.- πΊπΈUnited States jldust
I agree that this needs to be more extensive, I'm seeing these broken references with selection options as well.
- πΊπΈUnited States dcam
For anyone who needs a workaround, you can implement this in a custom theme or module:
/** * Implements hook_element_info_alter(). */ function my_theme_element_info_alter(array &$info) { $info['checkboxes']['#process'][] = '_my_theme_process_options_element'; $info['radios']['#process'][] = '_my_theme_process_options_element'; } /** * Processes checkboxes and radios elements. * * Checkboxes and radios have an accessibility bug where the child option * elements inherit an empty aria-describedby attribute from the parent. * Because the child elements are fully rendered before the parent, this can't * be handled in preprocess functions. * * @param array $element * An options form element. * * @return array * The processed options form element. * * @see https://www.drupal.org/project/drupal/issues/2839344 */ function _my_theme_process_options_element(array $element) { foreach ($element as $key => $value) { if (substr((string) $key, 0, 1) == '#') { continue; } if (!isset($value['#description']) && isset($value['#attributes']['aria-describedby'])) { unset($value['#attributes']['aria-describedby']); $element[$key] = $value; } } return $element; }
The same thing can be accomplished by adding a process function to individual checkbox and radio buttons. I tested it. Doing that means you don't need to loop through all the keys in the parent element to find its children. But my preference was to target the checkboxes and radios since they're the ones that have the problem.