Follow-up to #2972365: Unlabeled checkboxes for selecting bundles in workflow edit form → , where documentation would have helped.
For accessibility, it's important that the checkboxes used by Tableselect have accessible names. The Tableselect element does this by including a visually-hidden <label>
in the same column as the checkbox.
Module authors have to provide a string to make this label, but the documentation isn't clear how to do this. Crucially, if the module author doesn't provide a string for the label, the result is an UN-labeled checkbox in every row. Screen reader users are likely to face considerable difficulty using Tableselect. This is a WCAG failure at level-A - see F68: Failure of Success Criterion 4.1.2 due to a user interface control not having a programmatically determined name.
After studying core/modules/system/tests/modules/database_test/src/Form/DatabaseTestForm.php
and core/lib/Drupal/Core/Render/Element/Tableselect.php
, I learned that there is a special behaviour if row data contains the ['title']['data']['#title']
array structure. When this is set, the string is used as a label for the checkbox.
Here's an example from DatabaseTestForm::buildForm
. (The code comments here are mine).
// Note two column headers here. This doesn't include the column for the Tableselect checkboxes...
$header = [
'username' => ['data' => t('Username'), 'field' => 'u.name'],
'status' => ['data' => t('Status'), 'field' => 'u.status'],
];
// ... some database queries
$options = [];
foreach (User::loadMultiple($uids) as $account) {
$options[$account->id()] = [
// The 'title' key is special, note the array structure used.
// Drupal\Core\Render\Element\Tableselect::processTableSelect() looks
// for ['title']['data']['#title'], and uses this to label the Tableselect checkboxes if found.
'title' => ['data' => ['#title' => $account->getUsername()]],
// Remaining options correspond to columns named in $header above
'username' => $account->getUsername(),
'status' => $account->isActive() ? t('active') : t('blocked'),
];
}
$form['accounts'] = [
'#type' => 'tableselect',
'#header' => $header,
'#options' => $options,
'#empty' => t('No people available.'),
];
The actual processing of the special 'title' key is done in TableSelect::processTableselect()
.
Document the special behaviour of this 'title' key in TableSelect options array structure.
Where's the best place?
Tableselect
class DocBlock?Tableselect::processTableselect()
, which actually processes it?Patch.
None.
None.
None.
Active
10.1 ✨
Primarily changes documentation, not code. For Drupal core issues, select the Documentation component instead of using this tag. In general, component selection is preferred over tag selection.
It affects the ability of people with disabilities or special needs (such as blindness or color-blindness) to use Drupal.
Not all content is available!
It's likely this issue predates Contrib.social: some issue and comment data are missing.
No activities found.