Reply to comment

Drupal 8: Override views row (views-view-fields.html.twig) in views style plugin

In the last days I developed the ZURB Foundation Views integration module for Drupal 8. To match the markup required by foundation accordion we first had to write a views style plugin in our module. A tutorial on this topic can for example be found here: https://www.drupal.org/docs/8/creating-custom-modules/building-a-views-d...
Also you may have a look in our module code.

Beside the implementation of the various settings we then needed to override the views-view-fields.html.twig template to create the correct DOM structure. For example we had to

  • add a link wrapper to the first field
  • wrap all other fields into a div container
  • add various (data-)attributes and classes
  • handle special cases, for example with only one field

And that's where the trouble began. It wasn't easy to find out how to override that theme file (generally and especially only if our style plugin is active).

So what I was first looking for was a theme override based on the used style plugin, but that isn't implemented (Theme suggestions are created in ViewExecutable::buildThemeFunctions)
And I saw I opened Pandora's Box...

... as I found out that views doesn't use "hook_theme_suggestions" (see https://www.drupal.org/project/drupal/issues/2923634).
Even worse there are other problems with theme suggestions (see https://www.drupal.org/project/drupal/issues/2752443) and finally I had to find out that views-view-fields.html.twig is even special because it has no HOOK_theme implementation as it seems....

So after digging digging around the various issues I finally decided to use a different method and completely override the #theme hook for all rows. And that's the snippet I'd like to share with you, if you should run into a similar situation in your Drupal 8 views style plugin:

  1. /**
  2.  * Preprocess function for views_accordion_foundation_view template.
  3.  *
  4.  * Default template: views-accordion-foundation-view.html.twig.
  5.  *
  6.  * @{inheritdoc}
  7.  *
  8.  * We just want our own template to be able to guarantee some markup.
  9.  * @see template_preprocess_views_view_unformatted()
  10.  */
  11. function template_preprocess_views_accordion_foundation_view(&$variables) {
  12.   \Drupal::moduleHandler()->loadInclude('views', 'inc', 'views.theme');
  13.  
  14.   // [...] a lot of unrelated code for settings, etc.
  15.  
  16.   // We have to exchange the views_view_fields theme formatter with our own to do custom handling in view-views-accordion-foundation-fields.html.twig if our style plugin is active.
  17.   // This was hard and ugly to determine because theme suggestion altering doesn't work for <views_view_fields
  18.   if(!empty($variables['rows'])){
  19.     foreach($variables['rows'] as $key => $row){
  20.       foreach($variables['rows'][$key]['#theme'] as $idx => $theme_hook_suggestion){
  21.         // Replace views_view_fields suggestions with views_accordion_foundation_view_fields suggestions:
  22.         $variables['rows'][$key]['#theme'][$idx] = str_replace('views_view_fields', 'views_accordion_foundation_view_fields', $variables['rows'][$key]['#theme'][$idx]);
  23.       }      
  24.     }
  25.   }
  26.   // Delegate to default preprocess function from views now for doing all other stuff:
  27.   template_preprocess_views_view_unformatted($variables);
  28. }
  29.  
  30. /**
  31.  * Implements hook_theme().
  32.  */
  33. function views_accordion_foundation_theme($existing, $type, $theme, $path)
  34. {
  35.   // Add our own views-view-fields.html.twig implementation for this style plugin:
  36.   return array(
  37.     'views_accordion_foundation_view_fields' => array(
  38.       'variables' => array(
  39.         'view' => NULL,
  40.         'options' => [],
  41.         'row' => NULL,
  42.         'field_alias' => NULL,
  43.         'attributes' => [],
  44.         'title_attributes' => [],
  45.         'content_attributes' => [],
  46.         'title_prefix' => [],
  47.         'title_suffix' => [],
  48.         'fields' => []
  49.       ),
  50.       'path' => drupal_get_path('module', 'views_accordion_foundation') . '/templates',
  51.     ),
  52.   );
  53. }
  54.  
  55. function views_accordion_foundation_preprocess_views_accordion_foundation_view_fields(&$variables){
  56.   // Delegate the whole handling to the default views_view_fields implementation.
  57.   return template_preprocess_views_view_fields($variables);
  58. }

Did you run into the same problem or have a different solution? Please leave a comment.

Reply

The content of this field is kept private and will not be shown publicly.

More information about formatting options