Problem/Motivation

Drupal's theme system does not support tables with more than one row of table headers. Browsers support rendering multiple table headers and it can be useful for grouping/hierarchies of table header cells.

The idea of this feature request is to let users build table via the FAPI just as it was until then, but also to allow them to add one more depth level and let them build complex table header.

Further info:
http://jsfiddle.net/7pDqb/
http://stackoverflow.com/questions/18680044/how-can-i-construct-a-table-...

Proposed resolution

Update template_preprocess_table() method to let analyse headers with one more depth level, in a backward compatible way.
Update all table.html.twig files to reflect this change and support multiple rows of table headers.
Build a test to show the new feature and keep existing table test to show it's backward compatibility.

This would result in the ability to create this kind of headers via FAPI:
Complex header table

Remaining tasks

Design a solution and implement it.

User interface changes

none.

API changes

'#type' => 'table' FAPI element will support multiple row headers, that means the 'header' key would allow a one more depth level.
It may request another speical key to be achieved, but the exact API changes have to be discussed during implementation.

CommentFileSizeAuthor
#89 893530-multirow-header-d11.patch6.75 KBsimbaw
#73 Screen Shot 2023-03-08 at 1.43.27 PM.png34.5 KBsmustgrave
#73 Screen Shot 2023-03-08 at 1.39.32 PM.png32.72 KBsmustgrave
#72 893530-72-10-1-x.patch20 KBgauravvvv
#71 893530-71.patch25.33 KBkksandr
#70 893530-nr-bot.txt145 bytesneeds-review-queue-bot
#69 interdiff_68_69.txt361 bytesameymudras
#69 893530-69.patch24.13 KBameymudras
#68 893530-68.patch24.11 KBameymudras
#67 893530-64.patch23.66 KBameymudras
#64 893530-64.patch23.66 KBovanes
#61 interdiff_59-61.txt5.63 KBsuresh prabhu parkala
#61 893530-61.patch25.28 KBsuresh prabhu parkala
#60 893530-59.patch22.78 KBmgaskey
#58 893530-58.patch13.6 KBmgaskey
#54 interdiff_51_54.txt5.27 KBkiseleva.t
#54 893530-54.patch23.71 KBkiseleva.t
#51 interdiff_47-51.txt15.08 KBraman.b
#51 893530-51.patch25.5 KBraman.b
#47 interdiff-46-47.txt1.39 KBjungle
#47 893530-47.patch14.32 KBjungle
#46 drupal_allow-multirow-headers-893530-46.patch14.32 KBblackiceua
#39 drupal_allow-multirow-headers-893530-39.patch14.23 KBblackiceua
#35 interdiff-893530-32-35.txt813 bytesyogeshmpawar
#35 893530-35.patch14.11 KByogeshmpawar
#32 drupal_allow-multirow-headers-893530-32.patch14.13 KBblackiceua
#29 drupal_allow-multirow-headers-893530-29.patch14.38 KBjosebc
#25 header_multi_column.PNG2.86 KBdom.
#20 multilevel_headers--893530-20.patch13.92 KBdom.
#16 multilevel_headers--893530-14.patch13.92 KBdom.
#12 multilevel_headers--893530-11.patch12.67 KBdom.
#10 interdiff.txt3.02 KBdom.
#10 multilevel_headers--893530-10.patch12.67 KBdom.
#9 multilevel_headers--893530-9.patch12.09 KBdom.
#9 header_multi_column.PNG2.86 KBdom.

Issue fork drupal-893530

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

LEternity’s picture

Title: theme_table » theme_table and multiple header rows
Status: Active » Needs review

Since I couldn't find a viable solution for tables with more than one table headers, I wrote the following snippet myself. This solution has worked well for me! Please feel free to improve the code.

Paste the below code into your template.php file. Replace THEME with your theme prefix. Don't forget to flush your cache after saving changes in template.php!

Whenever you'd like to include additional rows, add a value for $rows_multiple other than NULL to your theme() function. (e.g. theme('table', $header, $row, $attributes, $caption, 'multiple')).

Your $header variable will now be able to take multiple arrays (see example below).

This would be part of your module.

$header[] = array('Hello','World');
$header[] = array('Bye', 'World');

Paste the following into your theme's template.php.

/**
* Modification of theme_table
*/
function THEME_table($header, $rows, $attributes = array(), $caption = NULL, $rows_multiple = NULL) {
 
  // Add sticky headers, if applicable.
  if (count($header)) {
    drupal_add_js('misc/tableheader.js');
    // Add 'sticky-enabled' class to the table to identify it for JS.
    // This is needed to target tables constructed by this function.
    $attributes['class'] = empty($attributes['class']) ? 'sticky-enabled' : ($attributes['class'] .' sticky-enabled');
  }

  $output = '<table'. drupal_attributes($attributes) .">\n";

  if (isset($caption)) {
    $output .= '<caption>'. $caption ."</caption>\n";
  }
   
    // Multiple header rows
    if(!$rows_multiple == NULL){
      $thead_set = '';
      // Format the table header:
      if (count($header)) {
          foreach($header as $number => $head){
            $ts = tablesort_init($head);
            // HTML requires that the thead tag has tr tags in it followed by tbody
            // tags. Using if clause to check and see if we have any rows and whether
            // the thead tag is already open
            if(count($rows) && $thead_set != 1){
                $output .= ' <thead><tr>';
                $thead_set = 1;
            }else{
                $output .= ' <tr>';
            }
            //$output .= (count($rows) ? ' <thead><tr>' : ' <tr>');
            foreach ($head as $cell) {
              $cell = tablesort_header($cell, $head, $ts);
              $output .= _theme_table_cell($cell, TRUE);
            }
        }
            // Using ternary operator to close the tags based on whether or not there are rows
            $output .= (count($rows) ? " </tr></thead>\n" : "</tr>\n");
      }
      else {
        $ts = array();
      }
    // One header row
    }else{
         // Format the table header:
      if (count($header)) {
        $ts = tablesort_init($header);
        // HTML requires that the thead tag has tr tags in it followed by tbody
        // tags. Using ternary operator to check and see if we have any rows.
        $output .= (count($rows) ? ' <thead><tr>' : ' <tr>');
        foreach ($header as $cell) {
          $cell = tablesort_header($cell, $header, $ts);
          $output .= _theme_table_cell($cell, TRUE);
        }
        // Using ternary operator to close the tags based on whether or not there are rows
        $output .= (count($rows) ? " </tr></thead>\n" : "</tr>\n");
      }
      else {
        $ts = array();
      }
    }
   
  // Format the table rows:
  if (count($rows)) {
    $output .= "<tbody>\n";
    $flip = array('even' => 'odd', 'odd' => 'even');
    $class = 'even';
    foreach ($rows as $number => $row) {
      $attributes = array();

      // Check if we're dealing with a simple or complex row
      if (isset($row['data'])) {
        foreach ($row as $key => $value) {
          if ($key == 'data') {
            $cells = $value;
          }
          else {
            $attributes[$key] = $value;
          }
        }
      }
      else {
        $cells = $row;
      }
      if (count($cells)) {
        // Add odd/even class
        $class = $flip[$class];
        if (isset($attributes['class'])) {
          $attributes['class'] .= ' '. $class;
        }
        else {
          $attributes['class'] = $class;
        }

        // Build row
        $output .= ' <tr'. drupal_attributes($attributes) .'>';
        $i = 0;
        foreach ($cells as $cell) {
          $cell = tablesort_cell($cell, $header, $ts, $i++);
          $output .= _theme_table_cell($cell);
        }
        $output .= " </tr>\n";
      }
    }
    $output .= "</tbody>\n";
  }

  $output .= "</table>\n";
  return $output;
}
thedavidmeister’s picture

Version: 6.x-dev » 8.0.x-dev
Issue summary: View changes
Status: Needs review » Needs work

This is an issue in d8 still, and has no patch so must be set to needs work.

Some extra reading on what this might look like:

http://stackoverflow.com/questions/18680044/how-can-i-construct-a-table-...

http://jsfiddle.net/7pDqb/

For reference, current table.html.twig looks like:

  {% if header %}
    <thead>
      <tr>
        {% for cell in header %}
          <{{ cell.tag }}{{ cell.attributes }}>
            {{- cell.content -}}
          </{{ cell.tag }}>
        {% endfor %}
      </tr>
    </thead>
  {% endif %}
mirakolous’s picture

Assigned: Unassigned » mirakolous
mirakolous’s picture

Assigned: mirakolous » Unassigned
joelpittet’s picture

Title: theme_table and multiple header rows » table template with multiple header rows
Version: 8.0.x-dev » 8.1.x-dev
Issue tags: +Twig

We need this to be backwards compatible way. And we are going to bump this to 8.1.x

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

Drupal 8.1.0-beta1 was released on March 2, 2016, which means new developments and disruptive changes should now 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.2.x-dev » 8.3.x-dev

Drupal 8.2.0-beta1 was released on August 3, 2016, which means new developments and disruptive changes should now 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.

dom.’s picture

Issue summary: View changes
dom.’s picture

Title: table template with multiple header rows » Multi level (multirow) header for table FAPI element
Status: Needs work » Needs review
StatusFileSize
new2.86 KB
new12.09 KB

In this patch, I make a suggestion that would let usual table work in a backward compatible way, as long as the overriden table.html.twig files are updated to add the new level loop.

The patch let's you use a new key called 'header_multirows' (boolean). By default, this key is FALSE and the former tables don't change.
If you set this flag to TRUE, you are indeed using multi row level headers and you must then give one more level to your 'header' key.
Using the patch attached, you can define a table as such:

$form[table'] = [
  '#type' => 'table',
  '#header' => [
    'row1' => [
      'bigcell' => [
        'data' => 'Big header',
        'rowspan' => 3
      ],
      'longcell' => [
        'data' => 'Long header',
        'colspan' => 2
      ],
      'Small header'
    ],
    'row2' => ['cell1', 'cell2', 'cell3']
  ],
  '#header_multirows' => TRUE,
  '#empty' => 'There are no lines here.',
];

And it would lead you to this ridiculously overrcomplicated table header ! :
Headerwith complex multilevel header

The patch attached includes:
- the functionnal changes to let this happen
- a test for this the functionnality

dom.’s picture

StatusFileSize
new12.67 KB
new3.02 KB

Simply correct rowspan since 2 is enough.
Also get rid of special NOTE about only one row support for header element.

Status: Needs review » Needs work

The last submitted patch, 10: multilevel_headers--893530-10.patch, failed testing.

dom.’s picture

Status: Needs work » Needs review
StatusFileSize
new12.67 KB

what's wrong with you patch ? ;)
Same patch again for reroll.

dawehner’s picture

+++ b/core/modules/system/templates/table.html.twig
@@ -60,13 +58,15 @@
   {% if header %}
     <thead>
-      <tr>
-        {% for cell in header %}
-          <{{ cell.tag }}{{ cell.attributes }}>
-            {{- cell.content -}}
-          </{{ cell.tag }}>
-        {% endfor %}
-      </tr>
+      {% for row in header %}
+        <tr>
+          {% for cell in row %}
+            <{{ cell.tag }}{{ cell.attributes }}>
+              {{- cell.content -}}
+            </{{ cell.tag }}>
+          {% endfor %}
+        </tr>
+      {% endfor %}

We should try to not break existing templates, so we should absolute not change the data passed along to a specific variable, but rather introduce a new one

dom.’s picture

@dawehner: I don't really understand... if the 'header' variable can store multiple rows, it has one more level. Therefore, if I should keep that 'header' variable as is and add a new one, let say 'header_multirow' that would contain the new variable. Then... the template still will need an update to use that new variable. Or did I miss something ?

dawehner’s picture

@dawehner: I don't really understand... if the 'header' variable can store multiple rows, it has one more level. Therefore, if I should keep that 'header' variable as is and add a new one, let say 'header_multirow' that would contain the new variable. Then... the template still will need an update to use that new variable. Or did I miss something ?

You are right, it needs an update, when you use multiple rows, but it at least doesn't break for tables with just one header row.

dom.’s picture

StatusFileSize
new13.92 KB

Hopefully this new patch is made here in a backward compatible way.

Yes table.html.twig are updated here too, but in a way that, if not (for instance a custom table.html.twig in a theme), the new feature won't work but the old feature with the simple header would still work without BC break.

To test it manually, you can apply the patch and run it's test: the new feature works. Then visit /admin/structure/block: it still works.
Now manually revert all table.html.twig template file. The new feature won't work, but /admin/structure/block still works => BC !

Status: Needs review » Needs work

The last submitted patch, 16: multilevel_headers--893530-14.patch, failed testing.

The last submitted patch, 16: multilevel_headers--893530-14.patch, failed testing.

dom.’s picture

Status: Needs work » Needs review
dom.’s picture

StatusFileSize
new13.92 KB

Change endfor to endif as appropriate.

dawehner’s picture

It would be great now if someone from the theme system team could have a look at.
@joelpittet, @laurii @cottser or someone else.

star-szr’s picture

I've only had a chance to quickly review but what would happen with an overridden table.html.twig when header_multilevel is TRUE (for example set by a contrib module)? Would it break or still show the old/standard header behaviour?

dom.’s picture

It should be tested for double check, but I guess it would break.
Since you are using a new functionnality from 8.y you have to update your template to 8.y, otherwise, without using the new functionnality, your 8.x template still work with you 8.x table.
Threfore is it also considered as a BC break ?

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

Drupal 8.3.0-alpha1 will be released the week of January 30, 2017, which means new developments and disruptive changes should now 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.

dom.’s picture

Issue summary: View changes
StatusFileSize
new2.86 KB
dom.’s picture

Issue tags: +DevDaysSeville

Adding issue tag, hoping for review !

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

Drupal 8.4.0-alpha1 will be released the week of July 31, 2017, which means new developments and disruptive changes should now 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.5.x-dev » 8.6.x-dev

Drupal 8.5.0-alpha1 will be released the week of January 17, 2018, which means new developments and disruptive changes should now 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.

josebc’s picture

re-roll for 6.x

dom.’s picture

Issue tags: -DevDaysSeville
markhalliwell’s picture

Status: Needs review » Needs work
+++ b/core/includes/theme.inc
@@ -832,6 +832,8 @@ function template_preprocess_image(&$variables) {
+ *   - header_multilevel: A boolean flag, FALSE by default. If set to TRUE, the

Instead of introducing an oddly named variable, why don't we just create headers which implies more than one and deprecate the usage of existing header variable?

blackiceua’s picture

Added possibility to use ordering with multirow headers. Based on drupal_allow-multirow-headers-893530-29.patch.

andrewmacpherson’s picture

Glad to find this issue. Very exciting, I'd love to see this capability in Drupal's theme layer.

It will need a detailed accessibility review before committing. I'll manually test it sometime, tagging for now.

Meanwhile, found in patch #32

diff --git a/core/includes/theme.inc b/core/includes/theme.inc
@@ -1767,7 +1800,7 @@ function drupal_common_theme() {
-      'variables' => ['header' => NULL, 'rows' => NULL, 'footer' => NULL, 'attributes' => [], 'caption' => NULL, 'colgroups' => [], 'sticky' => FALSE, 'responsive' => TRUE, 'empty' => ''],
+      'variables' => array('header' => NULL, 'header_multilevel' => NULL, 'rows' => NULL, 'footer' => NULL, 'attributes' => array(), 'caption' => NULL, 'colgroups' => array(), 'sticky' => FALSE, 'responsive' => TRUE, 'empty' => ''),

We should keep the short array [] syntax, current coding standards want it.

yogeshmpawar’s picture

Assigned: Unassigned » yogeshmpawar
yogeshmpawar’s picture

Assigned: yogeshmpawar » Unassigned
Status: Needs work » Needs review
StatusFileSize
new14.11 KB
new813 bytes

Addressed @andrewmacpherson comment in #33 & also added an interdiff for patches.

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

Drupal 8.6.0-alpha1 will be released the week of July 16, 2018, which means new developments and disruptive changes should now 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.

andrewbelcher’s picture

This works great for me! Would love to see this go in.

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

Drupal 8.7.0-alpha1 will be released the week of March 11, 2019, which means new developments and disruptive changes should now be targeted against the 8.8.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

blackiceua’s picture

Rerolled patch for 8.7.x

tamarpe’s picture

a/core/includes/theme.inc b/core/includes/theme.inc

+      foreach ($variables['header'] as $row_key => $header_row) {
+        foreach ($header_row as $col_key => $cell) {
+          if (isset($cell['field'])) {

$cell doesn't have to be an array, in that case, I'm getting:
Fatal error: Cannot use object of type Drupal\Core\Render\Markup as array in /app/www/core/includes/theme.inc on line 964

Added a check of array

Tested with 8.8.x

danchadwick’s picture

I would very much like this. The work-arounds are very awkward and brittle.

joegl’s picture

Would also love to see this! Thanks for all the hard work on this!

mgifford’s picture

@DanChadwick & @joegl could you test this? Even just on SimplyTest.me

https://simplytest.me/project/drupal/8.8.x?add[]=https://www.drupal.org/...

A screenshot with the header would be great.

joegl’s picture

We are still on 8.6.15 on the moment, and I'm hesitant to patch a core module since we'd have to push the patch out to all of our servers/platforms. That said, if I have some extra time today I will roll out a separate dev site to test this on.

EDIT: Tried to apply the patch to our 8.6.15 install but it failed at line 950 in the theme.inc file. I'll have to wait until we upgrade Drupal to test this one out, sorry about that.

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

Drupal 8.8.0-alpha1 will be released the week of October 14th, 2019, which means new developments and disruptive changes should now be targeted against the 8.9.x-dev branch. (Any changes to 8.9.x will also be committed to 9.0.x in preparation for Drupal 9’s release, but some changes like significant feature additions will be deferred to 9.1.x.). For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

blackiceua’s picture

Rerolled patch for 8.8.x

jungle’s picture

StatusFileSize
new14.32 KB
new1.39 KB

Fix coding standards

Status: Needs review » Needs work

The last submitted patch, 47: 893530-47.patch, failed testing. View results

jungle’s picture

There was 1 failure:

1) Drupal\KernelTests\Core\Theme\ConfirmClassyCopiesTest::testClassyHashes
table.html.twig has expected hash
Failed asserting that two strings are identical.
--- Expected
+++ Actual
@@ @@
-'8a3c6dc67452ec6372d56cfb496c711d'
+'2fc19df0265d6dd49d8b2b59560b9a2e'

Hi, there, is there an easy way to fix the file hash tests?

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

Drupal 8.9.0-beta1 was released on March 20, 2020. 8.9.x is the final, long-term support (LTS) minor release of Drupal 8, which means new developments and disruptive changes should now 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.

raman.b’s picture

Status: Needs work » Needs review
StatusFileSize
new25.5 KB
new15.08 KB

Re-rolling for 9.1.x

Resolving deprecations and updating table.html.twig for all the core themes

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.

cosolom’s picture

Status: Needs review » Needs work

This doesn't work for tableselect

kiseleva.t’s picture

StatusFileSize
new23.71 KB
new5.27 KB

Couldn't apply patch #51 for Drupal 8, modified that a bit for 8.9.x.

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.

akalata’s picture

Documentation for header_multilevel needs to be added under the "Available variables" section of the various table.html.twig files.

Also noticed a typo in the edit for header: "Each row contains and array" should be "Each row contains an array".

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.

mgaskey’s picture

StatusFileSize
new13.6 KB

Rerolling the patch from #47 for 9.3.0 (edit: failing)

mgaskey’s picture

mgaskey’s picture

StatusFileSize
new22.78 KB

In the end, I re-rolled the patch in #51 to work in 9.3.0

suresh prabhu parkala’s picture

Status: Needs work » Needs review
StatusFileSize
new25.28 KB
new5.63 KB

Tried to fix custom failures. Thanks.

avpaderno’s picture

Status: Needs review » Needs work
Issue tags: -th, -theme_table, -table header row

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.

ovanes’s picture

StatusFileSize
new23.66 KB

Patch 54 adjusted and re-rolled in order to work with Drupal 9.4.x

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.

mgifford’s picture

Issue tags: +wcag131, +atag, +we4authors

Relevant link https://www.w3.org/WAI/tutorials/tables/multi-level/

Worth looking at this example from We4Authors Cluster.
https://accessibilitycluster.com/main-results/table-creator

Would be associated with WCAG 1.3.1.

ameymudras’s picture

Status: Needs work » Needs review
StatusFileSize
new23.66 KB

Attempting to fix cspell issue. Couldn't generate interdiff because of whitespace issue

ameymudras’s picture

StatusFileSize
new24.11 KB

Adding the patch again for correct version

ameymudras’s picture

StatusFileSize
new24.13 KB
new361 bytes

Fixing ccf

needs-review-queue-bot’s picture

Status: Needs review » Needs work
StatusFileSize
new145 bytes

The Needs Review Queue Bot tested this issue. It either no longer applies to Drupal core, or fails the Drupal core commit checks. Therefore, this issue status is now "Needs work".

Apart from a re-roll or rebase, this issue may need more work to address feedback in the issue or MR comments. To progress an issue, incorporate this feedback as part of the process of updating the issue. This helps other contributors to know what is outstanding.

Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.

kksandr’s picture

StatusFileSize
new25.33 KB

Fix "Warning: Undefined array key "content" in claro_preprocess_table() (line 1015 of /var/www/web/core/themes/claro/claro.theme)"

gauravvvv’s picture

Status: Needs work » Needs review
StatusFileSize
new20 KB

I have attached re-rolled patch for 10.1.x. please review

smustgrave’s picture

Status: Needs review » Needs work
Issue tags: +Needs change record
StatusFileSize
new32.72 KB
new34.5 KB

Using the examples module with form API
Added this to the form (copied from the test)

    $form['table'] = [
      '#type' => 'table',
      '#header' => [
        'row1' => [
          'bigcell' => [
            'data' => 'Big header',
            'rowspan' => 2,
          ],
          'longcell' => [
            'data' => 'Long header',
            'colspan' => 2,
          ],
          'Small header',
        ],
        'row2' => ['cell1', 'cell2', 'cell3'],
      ],
      '#header_multilevel' => TRUE,
      '#empty' => 'There are no lines here.',
    ];

Had to switch to olivero theme but it seemed to show correctly
after

But tried with a contrib theme and it broke completely so a change record will be needed and regular tables will have to be tested to make sure this isn't introducing a bug to existing sites.

For accessibility
Using the ANDI testing tool
Got 2 errors for the cells in pink Scope association needed at intersection of

.
andi

Also got a warning Table has no [scope] associations. which may be unrelated here but worth mentioning.

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.

kksandr’s picture

Move changes from #71 to merge request

kksandr’s picture

sweetchuck’s picture

Has anybody tried this with a sticky table header?

rodrigoaguilera’s picture

I tested the latest MR and one thing I found weird is that the in the header array the indices for the rows can't be numeric.
Also when using multilevel the issues of having attributes in the headers cells is also solved, hence adding it as a related issue

liam morland made their first commit to this issue’s fork.

kovhan changed the visibility of the branch 893530-multirow-header to hidden.

kovhan changed the visibility of the branch 11.x to hidden.

liam morland’s picture

Status: Needs work » Needs review

kovhan changed the visibility of the branch 893530-multirow-header to active.

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.

kentr made their first commit to this issue’s fork.

kentr’s picture

Status: Needs review » Needs work

Many tests are failing.

hoporr’s picture

latest patch (8044) does no longer install against current Drupal 10.6.3

simbaw’s picture

StatusFileSize
new6.75 KB

Support Drupal 11.3.5