Document special 'title' key used for Tableselect checkbox labels

Created on 18 July 2018, over 6 years ago
Updated 20 January 2023, almost 2 years ago

Problem/Motivation

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().

Proposed resolution

Document the special behaviour of this 'title' key in TableSelect options array structure.
Where's the best place?

  • The Tableselect class DocBlock?
  • or the DockBlock for Tableselect::processTableselect(), which actually processes it?
  • Somewhere in the developer handbook pages?

Remaining tasks

Patch.

User interface changes

None.

API changes

None.

Data model changes

None.

📌 Task
Status

Active

Version

10.1

Component
Documentation 

Last updated 4 days ago

No maintainer
Created by

🇬🇧United Kingdom andrewmacpherson

Live updates comments and jobs are added and updated live.
  • Documentation

    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.

  • Accessibility

    It affects the ability of people with disabilities or special needs (such as blindness or color-blindness) to use Drupal.

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.

No activities found.

Production build 0.71.5 2024