Drupal 8 Views and Twig

Drupal 7 views were about the best thing ever and, thankfully, they’ve been included in Drupal 8 core. Strangely though, we find ourselves using less and less of them in Drupal 8 because of the ease and power of Twig.

We did notice that views are by far the most difficult thing to customize through Twig that we’ve found in D8. It's difficult to bring in content from one views field into another in a views field twig template—although it can be done with Twig in the Views UI rewrite. If we need to customize multiple fields on a view, we usually find ourselves rewriting the views display views-views-unformatted--myview--mydisplay.html.twig template—which can be an overkill if we are only customizing a couple of fields on the view.

We recently found that Views UI rewriting and the global custom text field stripped the audio formatting of a field we needed to group into a custom HTML structure with a couple of other fields. Our only choice was to render the field with the audio formatter and write the HTML needed around it and the other fields in the view display template itself.

We looped through the rows and found the row.content[‘#view’].style_plugin.render_tokens[ loop.index0 ] to get the field output. That gave the custom display template the rendered output of each field in the view—basically creating exactly what the view outputs without the views-field div wrappers. We could then print the rendered fields in the template in any order and with any HTML structure needed and the necessary rendered formatting.

If empty with views custom templates and Twig debugging

In the example above, we have some fields that we know are going to be constantly populated and some that aren’t. Since we’re writing custom HTML around the view fields, we need to use Twig’s {% if %} functionality to make sure that HTML is printed only when there is content to fill it. Normally it is very easy in Twig to write an if statement to include things if there is content to fill them. With views templates however, things we're not quite so easy. We tried hiding the rewriting on the field in Views UI. We tried hide if empty in the Views UI. We tried creating a views field template for that field and using a Twig if statement there to see if a lower level hierarchy or more specificity than just the rendered field in the display template would work.

Finally, we realized that Twig debug adds content to the view. All of that green ← THEME DEBUG → code you see in your browser inspector when debug is enabled counts as content to views. You can beat that by using Twig's |striptags|trim filters on your rendered views field output. For some fields though, you need to preserve some tags and Twig's autoescape function likes to print the tag as content in the views display template.

In the example above, we're printing the rendered body field of the podcast episode which can have HTML added by an editor. We could probably have set up some sort of Twig {{ autoescape false }} in the views field template for the body (by the time its rendered in the display template, its too late) and done it that way, but since debugging should only be used on local development sites, why bother? Turning debugging off in the services.yml file makes the if statements work as intended so we know that they will function properly when they get to production.