Same name and namespace in other branches
  1. 8.9.x core/includes/theme.inc \template_preprocess_table()
  2. 9 core/includes/theme.inc \template_preprocess_table()

Prepares variables for table templates.

Default template: table.html.twig.

Parameters

array $variables: An associative array containing:

  • header: An array containing the table headers. Each element of the array can be either a localized string or an associative array with the following keys:

    • data: The localized title of the table column, as a string or render array.
    • field: The database field represented in the table column (required if user is to be able to sort on this column).
    • sort: A default sort order for this column ("asc" or "desc"). Only one column should be given a default sort order because table sorting only applies to one column at a time.
    • initial_click_sort: Set the initial sort of the column when clicked. Defaults to "asc".
    • class: An array of values for the 'class' attribute. In particular, the least important columns that can be hidden on narrow and medium width screens should have a 'priority-low' class, referenced with the RESPONSIVE_PRIORITY_LOW constant. Columns that should be shown on medium+ wide screens should be marked up with a class of 'priority-medium', referenced by with the RESPONSIVE_PRIORITY_MEDIUM constant. Themes may hide columns with one of these two classes on narrow viewports to save horizontal space.
    • Any HTML attributes, such as "colspan", to apply to the column header cell.
  • rows: An array of table rows. Every row is an array of cells, or an associative array with the following keys:

    • data: An array of cells.
    • Any HTML attributes, such as "class", to apply to the table row.
    • no_striping: A Boolean indicating that the row should receive no 'even / odd' styling. Defaults to FALSE.

    Each cell can be either a string or an associative array with the following keys:

    • data: The string or render array to display in the table cell.
    • header: Indicates this cell is a header.
    • Any HTML attributes, such as "colspan", to apply to the table cell.

    Here's an example for $rows:

$rows = array(
  // Simple row
  array(
    'Cell 1',
    'Cell 2',
    'Cell 3',
  ),
  // Row with attributes on the row and some of its cells.
  array(
    'data' => array(
      'Cell 1',
      array(
        'data' => 'Cell 2',
        'colspan' => 2,
      ),
    ),
    'class' => array(
      'funky',
    ),
  ),
);
  • footer: An array of table rows which will be printed within a <tfoot> tag, in the same format as the rows element (see above).
  • attributes: An array of HTML attributes to apply to the table tag.
  • caption: A localized string to use for the <caption> tag.
  • colgroups: An array of column groups. Each element of the array can be either:

    • An array of columns, each of which is an associative array of HTML attributes applied to the <col> element.
    • An array of attributes applied to the <colgroup> element, which must include a "data" attribute. To add attributes to <col> elements, set the "data" attribute with an array of columns, each of which is an associative array of HTML attributes.

    Here's an example for $colgroup:

$colgroup = array(
  // <colgroup> with one <col> element.
  array(
    array(
      'class' => array(
        'funky',
      ),
    ),
  ),
  // <colgroup> with attributes and inner <col> elements.
  array(
    'data' => array(
      array(
        'class' => array(
          'funky',
        ),
      ),
    ),
    'class' => array(
      'jazzy',
    ),
  ),
);

These optional tags are used to group and set properties on columns within a table. For example, one may easily group three columns and apply same background style to all.

  • sticky: Use a "sticky" table header.
  • empty: The message to display in an extra row if table does not have any rows.
1 call to template_preprocess_table()
template_preprocess_field_ui_table in core/modules/field_ui/field_ui.module
Prepares variables for field UI overview table templates.

File

core/includes/theme.inc, line 916
The theme system, which controls the output of Drupal.

Code

function template_preprocess_table(&$variables) {

  // Format the table columns:
  if (!empty($variables['colgroups'])) {
    foreach ($variables['colgroups'] as &$colgroup) {

      // Check if we're dealing with a simple or complex column
      if (isset($colgroup['data'])) {
        $cols = $colgroup['data'];
        unset($colgroup['data']);
        $colgroup_attributes = $colgroup;
      }
      else {
        $cols = $colgroup;
        $colgroup_attributes = [];
      }
      $colgroup = [];
      $colgroup['attributes'] = new Attribute($colgroup_attributes);
      $colgroup['cols'] = [];

      // Build columns.
      if (is_array($cols) && !empty($cols)) {
        foreach ($cols as $col_key => $col) {
          $colgroup['cols'][$col_key]['attributes'] = new Attribute($col);
        }
      }
    }
  }

  // Build an associative array of responsive classes keyed by column.
  $responsive_classes = [];

  // Format the table header:
  $ts = [];
  $header_columns = 0;
  if (!empty($variables['header'])) {
    $ts = TableSort::getContextFromRequest($variables['header'], \Drupal::request());

    // Use a separate index with responsive classes as headers
    // may be associative.
    $responsive_index = -1;
    foreach ($variables['header'] as $col_key => $cell) {

      // Increase the responsive index.
      $responsive_index++;
      if (!is_array($cell)) {
        $header_columns++;
        $cell_content = $cell;
        $cell_attributes = new Attribute();
        $is_header = TRUE;
      }
      else {
        if (isset($cell['colspan'])) {
          $header_columns += $cell['colspan'];
        }
        else {
          $header_columns++;
        }
        $cell_content = '';
        if (isset($cell['data'])) {
          $cell_content = $cell['data'];
          unset($cell['data']);
        }

        // Flag the cell as a header or not and remove the flag.
        $is_header = $cell['header'] ?? TRUE;
        unset($cell['header']);

        // Track responsive classes for each column as needed. Only the header
        // cells for a column are marked up with the responsive classes by a
        // module developer or themer. The responsive classes on the header cells
        // must be transferred to the content cells.
        if (!empty($cell['class']) && is_array($cell['class'])) {
          if (in_array(RESPONSIVE_PRIORITY_MEDIUM, $cell['class'])) {
            $responsive_classes[$responsive_index] = RESPONSIVE_PRIORITY_MEDIUM;
          }
          elseif (in_array(RESPONSIVE_PRIORITY_LOW, $cell['class'])) {
            $responsive_classes[$responsive_index] = RESPONSIVE_PRIORITY_LOW;
          }
        }
        TableSort::header($cell_content, $cell, $variables['header'], $ts);

        // TableSort::header() removes the 'sort', 'initial_click_sort' and
        // 'field' keys.
        $cell_attributes = new Attribute($cell);
      }
      $variables['header'][$col_key] = [];
      $variables['header'][$col_key]['tag'] = $is_header ? 'th' : 'td';
      $variables['header'][$col_key]['attributes'] = $cell_attributes;
      $variables['header'][$col_key]['content'] = $cell_content;
    }
  }
  $variables['header_columns'] = $header_columns;

  // Rows and footer have the same structure.
  $sections = [
    'rows',
    'footer',
  ];
  foreach ($sections as $section) {
    if (!empty($variables[$section])) {
      foreach ($variables[$section] as $row_key => $row) {
        $cells = $row;
        $row_attributes = [];

        // Check if we're dealing with a simple or complex row
        if (isset($row['data'])) {
          $cells = $row['data'];
          $variables['no_striping'] = $row['no_striping'] ?? FALSE;

          // Set the attributes array and exclude 'data' and 'no_striping'.
          $row_attributes = $row;
          unset($row_attributes['data']);
          unset($row_attributes['no_striping']);
        }

        // Build row.
        $variables[$section][$row_key] = [];
        $variables[$section][$row_key]['attributes'] = new Attribute($row_attributes);
        $variables[$section][$row_key]['cells'] = [];
        if (!empty($cells)) {

          // Reset the responsive index.
          $responsive_index = -1;
          foreach ($cells as $col_key => $cell) {

            // Increase the responsive index.
            $responsive_index++;
            if (!is_array($cell)) {
              $cell_content = $cell;
              $cell_attributes = [];
              $is_header = FALSE;
            }
            else {
              $cell_content = '';
              if (isset($cell['data'])) {
                $cell_content = $cell['data'];
                unset($cell['data']);
              }

              // Flag the cell as a header or not and remove the flag.
              $is_header = !empty($cell['header']);
              unset($cell['header']);
              $cell_attributes = $cell;
            }

            // Active table sort information.
            if (isset($variables['header'][$col_key]['data']) && $variables['header'][$col_key]['data'] == $ts['name'] && !empty($variables['header'][$col_key]['field'])) {
              $variables[$section][$row_key]['cells'][$col_key]['active_table_sort'] = TRUE;
            }

            // Copy RESPONSIVE_PRIORITY_LOW/RESPONSIVE_PRIORITY_MEDIUM
            // class from header to cell as needed.
            if (isset($responsive_classes[$responsive_index])) {
              $cell_attributes['class'][] = $responsive_classes[$responsive_index];
            }
            $variables[$section][$row_key]['cells'][$col_key]['tag'] = $is_header ? 'th' : 'td';
            $variables[$section][$row_key]['cells'][$col_key]['attributes'] = new Attribute($cell_attributes);
            $variables[$section][$row_key]['cells'][$col_key]['content'] = $cell_content;
          }
        }
      }
    }
  }
  if (empty($variables['no_striping'])) {
    $variables['attributes']['data-striping'] = 1;
  }
}