Change record status: 
Project: 
Introduced in branch: 
11.4.x
Introduced in version: 
11.4.0
Description: 

hook_preprocess_views_view_grouping() was only invoked for nested (multi-level) grouping. For single-level grouping, StylePluginBase::renderGroupingSets() bypassed the views_view_grouping theme hook and delegated directly to renderRowGroup(), which uses the style's own theme (e.g. views_view_unformatted). The preprocess hook was therefore never triggered.

Two changes have been made to fix this:

  1. StylePluginBase::renderGroupingSets()

    At the leaf level (rows are individual result rows, not nested groups), when grouping is configured, the method now builds a #theme => views_view_grouping render array instead of calling renderRowGroup() directly. This ensures hook_preprocess_views_view_grouping() is invoked at every grouping level.

    Before:

    // Leaf rows always went through renderRowGroup(), skipping views_view_grouping.
    $single_output = $this->renderRowGroup($set['rows']);
    

    After:

    if (!empty($this->options['grouping'])) {
      $single_output = [
        '#theme' => $theme_functions,
        '#view' => $this->view,
        '#grouping' => $this->options['grouping'][$level] ?? [],
        '#rows' => $set['rows'],
      ];
    }
    else {
      $single_output = $this->renderRowGroup($set['rows']);
    }
    
  2. ViewsThemeHooks::preprocessViewsViewGrouping()

    The preprocess function now detects whether $variables['rows'] contains nested grouping sets (arrays with a 'group' key) or already-rendered rows (leaf level), and handles each case:

    • Non-leaf level: calls renderGroupingSets() recursively, as before.
    • Leaf level (including single-level grouping): wraps the rows in the style's own theme render array.

    $variables['content'] is now always an indexed array of render arrays at every level.

    Additionally, $variables['title'] is now wrapped in a Markup object to prevent Twig from double-escaping the already-HTML-escaped rendered field value used as the group title.

Impact on site builders and module developers

This change affects you if you have:

  • A custom views-view-grouping.html.twig template — it will now also be invoked for single-level grouping, where it was previously skipped. Review your template to ensure it handles both leaf and non-leaf levels correctly.
  • A hook_preprocess_views_view_grouping() implementation — it will now fire for all grouping levels. The $variables['content'] variable is always an indexed array of render arrays; if your hook assumed a different structure for single-level grouping, update it accordingly.
  • A hook_preprocess_views_view_grouping() implementation that outputs $variables['title'] — it is now a Markup object; do not re-escape it.
Impacts: 
Module developers
Themers