Problem/Motivation

It is desirable to be able to output table rows in multiple tbody elements. This can be used for semantic grouping and styling.

One use case (original report): The possibility to group table rows with tbody is needed for the redesigned permissions page, #30843: Redesign permissions page. Even though that is probably a rare case the functionality could be useful in other situations as well, e.g. if you would like to have a group of rows to have a distinct color.

Proposed resolution

Here is some example code to illustrate:

<table>
  <thead>
    <tr><th>...header information...</th></tr>
  </thead>
  <tbody class="even collapsible collapsed">
    <tr><td>...first row of block one data...<td></tr>
    <tr><td>...second row of block one data...<td></tr>
  </tbody>
  <tbody class="odd collapsible collapsed">
    <tr><td>...first row of block two data...<td></tr>
    <tr><td>...second row of block two data...<td></tr>
    <tr><td>...third row of block two data...<td></tr>
  </tbody>
</table>

Remaining tasks

  1. Agree on the properties which will be used to express this in render arrays.
  2. Implement by updating template_preprocess_table() and table.html.twig.

User interface changes

None; this is a feature for developers.

API changes

template_preprocess_table() accepts a new variable, #rowgroups:

#rowgroups = [
  [
    'rows' => $rows, // Same as #rows.
    ..., // Attributes to put on the tbody.
  ],
  $more_rows_1, // Further rowgroups.
  $more_rows_2,
];

If both #rowgroups and #rows are specified, put the #rows in their own tbody before the contents of #rowgroups.

Issue fork drupal-31535

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:

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

anders.fajerson’s picture

Ignore the part about optional end tag, it was the HTML 4.01 Specification, my mistake...

LAsan’s picture

Version: x.y.z » 7.x-dev
Status: Active » Fixed
dvessel’s picture

Status: Fixed » Active

LAsan, careful on setting the status. This isn't fixed.

This should be combined with column groups. http://drupal.org/node/239071

The question is how to implement this without making it too complicated.

Wim Leers’s picture

That one has been commited, so we should work on this issue separately now.

Wim Leers’s picture

Version: 7.x-dev » 8.x-dev
casey’s picture

Subscribing. Too bad we didn't get this in in D7.

Wim Leers’s picture

Well, if you provide the patch *now*, it can get in D8 very early :)

casey’s picture

Status: Active » Needs review
FileSize
5.96 KB
RobLoach’s picture

Status: Needs review » Needs work

Would be nice to have a use case of the $row_groups in Drupal core when this goes in. Maybe apply it to the permissions page in this patch? I'm all for this going into Drupal 7 if it means cleaning up user_admin_permissions() and theme_user_admin_permissions().

casey’s picture

Version: 8.x-dev » 7.x-dev
Status: Needs work » Needs review
FileSize
10.7 KB

#125099: theme_table() should accept attributes for the THEAD and TBODY tags and header TR tag
Patch allows attributes for tbody.

Also implemented rowgroups for admin user permissions, which is a good excuse to get this in D7.

casey’s picture

casey’s picture

FileSize
10.71 KB

Reroll.

retester2010’s picture

#12: theme_table.patch queued for re-testing.

Status: Needs review » Needs work

The last submitted patch, theme_table.patch, failed testing.

casey’s picture

Version: 7.x-dev » 8.x-dev
casey’s picture

Status: Needs work » Needs review
FileSize
10.28 KB
klonos’s picture

...subscribing.

Now that we have editable issue summaries, I updated it a bit by removing the mention of the optional end tbody tag as per #1 above.

@casey: Care to also explain what the patch does, what neds testing/review and perhaps update the issue summary too? Thanx

klonos’s picture

Issue summary: View changes

...removed the comment on optional end tag of

as per comment #1
klonos’s picture

...edited the summary once more to add the template from Issue summary standards. I left blank the sections where I cannot possibly know what needs to be added there. Hopefully this is enough help to get one started ;)

klonos’s picture

Issue summary: View changes

...conforming to the Issue summary standards.

sun’s picture

Let me try to give some direction here.

1) This addition adds even more insanity to the already insane theme_table(). No themer on this earth is going to be able to override theme_table() any longer. I'd like to see the entire table structure (especially regarding colgroups and rowgroups) prepared in a template_preprocess_table() function (preprocessors are no longer limited to templates since D7). The complex code logic needs to be hidden away from themers. The resulting theme function should only (and always) get rows and columns in groups, essentially decreasing the function body to a couple of simple foreach()s in the ideal case.

2) "rowgroups" is a kinda strange variable name. The existing "colgroups" at least maps to more or less direct equivalent HTML tags. "rowgroups", however, is converted and translated into "tbody" tags.

3) We need to be careful to not break tableDrag with this change; or in other words: tableDrag potentially needs to be updated to work with rowgroups, too.

4) Speaking of, it seems like this patch could and possibly should simplify the existing "row grouping" implementations we already have in core - on Block module's administrative block overview page, and Field UI's Manage fields as well as Display fields pages.

5) The changes to the user permissions page/table need to be removed from this patch.

6) Existing unit tests for theme_table() need to be enhanced to assert expectations for this functionality.

7) Lastly, we have to discuss whether it wouldn't make more sense to make a more far-reaching change and require the $rows array to always contain groups on the top-level. I.e.,

$rows = array();
$row = array('one', 'two', 'three');
$rows[] = $row;
theme('table', array('rows' => $rows));

would become

$groups = array();
$rows = array();
$row = array('one', 'two', 'three');
$rows[] = $row;
$groups[''] = $rows;
theme('table', array('rows' => $groups));
xjm’s picture

Status: Needs review » Needs work

I think this is NW for sun's feedback in #19.

xjm’s picture

Issue summary: View changes

API changes

nod_’s picture

We're going to need that for some JS cleanup and very likely for the tabledrag rewrite.

nod_’s picture

nod_’s picture

Issue summary: View changes

...formatting link to issue with [#...] so that status is directly visible.

nod_’s picture

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

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.

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.

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.

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.

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.

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.

Liam Morland’s picture

Title: Grouping of rows in theme_table() » Grouping of rows in table.html.twig

This needs a completely different patch because of #1939008: Convert theme_table() to Twig. Because of this change, the patch can be simpler. There is relevant code in class Table and template_preprocess_table().

I think it is reasonable to use #rowgroups; that maps onto the rowgroup value for the scope attribute. Or it could be #tbodys. It doesn't matter to me.

If both #rows and #rowgroups are set, the template could display the rows from #rows then those from #rowgroups to keep backward compatibility.

I propose that the value of #rowgroups be like this:

#rowgroups = [
  [
    'rows' => $rows, // Same as #rows.
    ..., // Attributes to put on the tbody.
  ],
  $more_rows_1, // Further rowgroups.
  $more_rows_2,
];

Making the table theming more powerful should be separate from putting the new features to use, such as in the permissions page as suggested above.

If people are agreeable with this proposal, I will start implementing it.

Liam Morland’s picture

Title: Grouping of rows in table.html.twig » Allow table row groups in table.html.twig and template_preprocess_table()
Component: theme system » sqlite db driver
Issue summary: View changes
Liam Morland’s picture

Status: Needs work » Active
markhalliwell’s picture

Component: sqlite db driver » theme system
Status: Active » Needs work
Liam Morland’s picture

Status: Needs work » Active

Sorry about "sqlite db driver"; that was unintentional.

There is no patch to review right now; all patches on this issue are pre-Twig and as such, obsolete. What is needed is discussion about the proposed solution.

Liam Morland’s picture

Does anyone have thoughts about the proposal in #32? I'd love to hear feedback from anyone, in particular, the followers of this ticket.

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.

BradK’s picture

I just found that I needed this functionality. Yes, #32 sounds like a solid implementation. #rowgroups seems the intuitive element to place it in.

Thanks for this!

nod_’s picture

Seems good to me too, would #rowgroups have additional properties, like #title or something? if we look at the mockups for the permissions page that this was needed for there is a sort of "label" for the group.

Liam Morland’s picture

How would the #title be displayed?

Rowgroups can be labelled by a th with scope="rowgroup".

Liam Morland’s picture

Here is an initial patch implementing #rowgroups. It doesn't update all the table templates that come with core but it is enough to demonstrate the approach. Any rows in #rows are added to be beginning of #rowgroups in their own group. After the rows are processed, #rows is made to contain pointers to all the rows in #rowgroups. So, a template can render either #rowgroups or #rows and it will get all the rows, so it is backwards-compatible with templates that do not support #rowgroups.

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.

Liam Morland’s picture

Created merge request with patch #42.

(I don't know why comment #44 was generated. I just created an issue fork and it seems to have created a merge request at the same time, before there was any commit to merge.)

Liam Morland’s picture

The tests failed with "Custom Commands Failed". I don't think this patch uses any custom commands, so I don't think this patch is the cause of the test failure.

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.

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.

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

travis-bradbury’s picture

The failure is from a spell checker:

/var/www/html/core/includes/theme.inc:916:8 - Unknown word (rowgroups)
/var/www/html/core/includes/theme.inc:921:28 - Unknown word (rowgroups)
/var/www/html/core/includes/theme.inc:922:54 - Unknown word (rowgroups)
/var/www/html/core/includes/theme.inc:923:31 - Unknown word (rowgroups)
/var/www/html/core/modules/system/templates/table.html.twig:21:6 - Unknown word (rowgroups)
/var/www/html/core/modules/system/templates/table.html.twig:76:9 - Unknown word (rowgroups)
/var/www/html/core/modules/system/templates/table.html.twig:77:24 - Unknown word (rowgroups)
/var/www/html/core/themes/seven/templates/classy/dataset/table.html.twig:21:6 - Unknown word (rowgroups)
/var/www/html/core/themes/seven/templates/classy/dataset/table.html.twig:79:9 - Unknown word (rowgroups)
/var/www/html/core/themes/seven/templates/classy/dataset/table.html.twig:80:24 - Unknown word (rowgroups)

I added 'rowgroup' and 'rowgroups' to the dictionary. I don't know whether it's common jargon or not, but it's defined in the documentation where we're using it, so I don't see a problem adding it to the dictionary.

travis-bradbury’s picture

Status: Needs review » Needs work

There's a couple issues: in core/modules/system/templates/table.html.twig. Looks like core/themes/seven/templates/classy/dataset/table.html.twig is correct though.

  • There's a missing {% endif %}.
  • {% if rows %} should be {% if rowgroup.rows %}

I think that's why the tests don't work right now. The last job (https://www.drupal.org/pift-ci-job/2363868) shows a ton of fails (https://dispatcher.drupalci.org/job/drupal_patches/124754/). The problem with the twig template causes a fatal error, and that'd probably explain so many broken pages.

The branch is also based off of 9.2.x, but should probably be for 10 first, then backported to 9.4.

andregp’s picture

I was creating a reroll for D10 with #51 corrections, but when I ran a PHPStan check it returned the following error:

  Line   includes/theme.inc                       
 ------ ----------------------------------------- 
  1102   Undefined variable: $ts                  
  1108   Undefined variable: $responsive_classes  

Looking deeper into the code I noticed that this piece of code:

if (isset($variables['header'][$col_key]['data']) && $variables['header'][$col_key]['data'] == $ts['name'] && !empty($variables['header'][$col_key]['field'])) {
  $row['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];
}

Was moved from the template_preprocess_table() function to _template_preprocess_table_process_rows() where these variables are not defined. I don't know the right solution. I though about passing them as argument to _template_preprocess_table_process_rows() but this sounded too much hacky and wrong.

Also, regarding comment #51, I could not find the missing {% endif %} on either templates/table.html.twig or dataset/table.html.twig. Both of them have exactly 6 {% if ... and 6 {% endif %}.

travis-bradbury’s picture

I just pushed a change to fix core/modules/system/templates/table.html.twig. It's still based on 9.2.x but it should be interesting to see what happens with the tests this time.

The undefined variables that #52 pointed out are still not addressed.

travis-bradbury’s picture

Status: Needs work » Needs review

The last commit fixes the undefined variables $ts and $responsive_classes by passing them in to the new function. That fixed one of the kernel tests, so I hope it fixes the functional tests too (I didn't run them, so we'll see what CI says). The other kernel test that was failing was a test of Classy assets, which requires that all themes that copy from Classy to have identical files, so I copied table.html.twig to Classy and the rest of the themes that borrow from it, and I updated the md5 sum of table.html.twig in the test (for more info about what's going on there, this is the test https://dispatcher.drupalci.org/job/drupal_patches/124891/testReport/jun...)

This would still need to be rebased on 10.x / 9.4 / etc.

travis-bradbury’s picture

The last two changes:

travis-bradbury’s picture

The last last commit adds rowgroups to the theme definition in drupal_common_theme and Table::getInfo, and adds a test to the TableTest kernel test.

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.

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.

smustgrave’s picture

Status: Needs review » Needs work

Can the MR please be updated for 10.1

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.