Drupal 8 Views Style Swagger

Portland Maine - Drupal 8 has been a pleasure to work with but sometimes when we attempt to exercise our Drupal 7 muscle memory a cramp occurs. When our amazing designer provide us with PSDs I start deciding the best approach to bring the design to life. Often times a Drupal View is the right approach but being subjected to the style output from Views is a pain. I'd rather take complete control of the mark up and methodically render the data that Views gives me inside a template file. This usually saves me a lot of time messing with CSS and cross browser issues because I am constructing the HTML to fit the design instead of fighting what Views provides me with CSS. In Drupal 7 if the design fits in the Unformatted HTML style I will grab that template file and go to work. From this template we have access to the completely rendered "row" but we can also drill into the row data and pull out each View's field value. In Drupal 8 the styles template layer doesn't provide access to the View's field data like it did in Drupal 7. This caused me some headaches, because even though I could access the entity from either Twig or with a preprocessor (template_preprocess_views_view_unformatted) I could not render the View's field value as it was intended or described in the View's cockpit. For example, if I was rendering a date field in the view's unformatted style Twig template, I could drill into the entity's stored field value but it would be in UTC format. Or if a Site Builder has overwritten the View's field value via the cockpit, I could not access this via the style template.

In order to remedy this I wrote a preprocessor function for the "unformatted" views style template and included all the field values. I basically took the logic from template_preprocess_views_view_fields() and included it in template_preprocess_views_view_unformatted(). Now it behaves like Drupal 7 giving me access the the field outputs inside the style template layer. Remember this preprocessor is occurring after the Views module's initial preprocessor.

// This can go in your theme's mytheme.theme file.
* Implements template_preprocess_views_view_unformatted().
function mytheme_preprocess_views_view_unformatted(&$variables) {
$view = $variables['view'];
$style = $view->style_plugin;
$options = $style->options;
$variables['default_row_class'] = !empty($options['default_row_class']);
foreach ($variables['rows'] as $id => $row_data) {
// Loop through the fields for this row.
$previous_inline = FALSE;
$variables['fields'] = array(); // ensure it's at least an empty array.
/** @var \Drupal\views\ResultRow $row */
$row = $row_data['content']['#row'];
foreach ($view->field as $id => $field) {
// render this even if set to exclude so it can be used elsewhere.
$field_output = $view->style_plugin->getField($row->index, $id);
$empty = $field->isValueEmpty($field_output, $field->options['empty_zero']);
if (empty($field->options['exclude']) && (!$empty || (empty($field->options['hide_empty']) && empty($variables['options']['hide_empty'])))) {
$object = new stdClass();
$object->handler = $view->field[$id];
$object->inline = !empty($variables['options']['inline'][$id]);
// Set up default value of the flag that indicates whether to display a
// colon after the label.
$object->has_label_colon = FALSE;
$object->element_type = $object->handler->elementType(TRUE, !$variables['options']['default_field_elements'], $object->inline);
if ($object->element_type) {
$attributes = array();
if ($object->handler->options['element_default_classes']) {
$attributes['class'][] = 'field-content';
if ($classes = $object->handler->elementClasses($row->index)) {
$attributes['class'][] = $classes;
$object->element_attributes = new Drupal\Core\Template\Attribute($attributes);
$object->content = $field_output;
if (isset($view->field[$id]->field_alias) && isset($row->{$view->field[$id]->field_alias})) {
$object->raw = $row->{$view->field[$id]->field_alias};
else {
$object->raw = NULL; // make sure it exists to reduce NOTICE
if (!empty($variables['options']['separator']) && $previous_inline && $object->inline && $object->content) {
$object->separator = Drupal\Component\Utility\Xss::filterAdmin($variables['options']['separator']);
$object->class = Drupal\Component\Utility\Html::cleanCssIdentifier($id);
$previous_inline = $object->inline;
// Set up field wrapper element.
$object->wrapper_element = $object->handler->elementWrapperType(TRUE, TRUE);
if ($object->wrapper_element === '' && $variables['options']['default_field_elements']) {
$object->wrapper_element = $object->inline ? 'span' : 'div';
// Set up field wrapper attributes if field wrapper was set.
if ($object->wrapper_element) {
$attributes = array();
if ($object->handler->options['element_default_classes']) {
$attributes['class'][] = 'views-field';
$attributes['class'][] = 'views-field-' . $object->class;
if ($classes = $object->handler->elementWrapperClasses($row->index)) {
$attributes['class'][] = $classes;
$object->wrapper_attributes = new Drupal\Core\Template\Attribute($attributes);
// Set up field label
$object->label = $view->field[$id]->label();
// Set up field label wrapper and its attributes.
if ($object->label) {
// Add a colon in a label suffix.
if ($object->handler->options['element_label_colon']) {
$object->label_suffix = ': ';
$object->has_label_colon = TRUE;
// Set up label HTML element.
$object->label_element = $object->handler->elementLabelType(TRUE, !$variables['options']['default_field_elements']);
// Set up label attributes.
if ($object->label_element) {
$attributes = array();
if ($object->handler->options['element_default_classes']) {
$attributes['class'][] = 'views-label';
$attributes['class'][] = 'views-label-' . $object->class;
// Set up field label.
$element_label_class = $object->handler->elementLabelClasses($row->index);
if ($element_label_class) {
$attributes['class'][] = $element_label_class;
$object->label_attributes = new Drupal\Core\Template\Attribute($attributes);
$variables['fields'][$id] = $object;

Now in your views-view-unformatted.html.twig you can gain access to the field values like so:

{{ fields.field_name.content }}

For more information, take a look at views-view-field.html.twig. The Twig variables that you have here are now available at your style template layer. This same preprocessor for views_view_unformatted could theoretically be used in any of the other style formats preprocessors.

Comments (0)

About Us

We are web developers versed in front and back end technologies. We like PHP, Drupal and Wordpress for our web apps and Foundation, Bootstrap, SUSY and Sass for our User Interfaces. Contact us to be apart of your next web project.

Latest Articles

Copyright © 2020 Focal55 Inc. / All rights reserved.