Tutorial: How to Group Fields in Views With a Div or Span Tag

This is a howto for wrapping a div around a few of your view fields (and not others). This is useful, for instance, for being able to group all one's content so that it floats left but does not float around an image.

EDIT: This technique is a good intro to views templates, however, an easier way exists which seems a little hackish, but would work for many use cases. Thanks to Sr. or Sra. Anonymous.

EDIT #2: Another way to create this effect is to use the "Table" layout under "Style" settings for your view. Everyone loves to hate on tables, but they get the job done.

Just use one "Global:Custom" field with a single div tag in it. See screenshot. It will span from that element until the last field in the view row. You can insert another "Global:Custom" field which can be nested inside the previous. However, I do not see a way to use this to create two sibling field groupings, so this post is still useful for learning about views templating and will give you you complete control over your markup.

Carry on.

First, create a template for your view.

Create a template file in your theme directory with the same name as the views and paste the code from the level of specificity that you desire. For more information, read this introduction to views template files.

Here is the code from the stock Row Style Output:

<?php
// $Id: views-view-fields.tpl.php,v 1.6 2008/09/24 22:48:21 merlinofchaos Exp $
/**
 * @file views-view-fields.tpl.php
 * Default simple view template to all the fields as a row.
 *
 * - $view: The view in use.
 * - $fields: an array of $field objects. Each one contains:
 *   - $field->content: The output of the field.
 *   - $field->raw: The raw data for the field, if it exists. This is NOT output safe.
 *   - $field->class: The safe class id to use.
 *   - $field->handler: The Views field handler object controlling this field. Do not use
 *     var_export to dump this object, as it can't handle the recursion.
 *   - $field->inline: Whether or not the field should be inline.
 *   - $field->inline_html: either div or span based on the above flag.
 *   - $field->separator: an optional separator that may appear before a field.
 * - $row: The raw result object from the query, with all data it fetched.
 *
 * @ingroup views_templates
 */

?>
<?php foreach ($fields as $id => $field): ?>
  <?php if (!empty($field->separator)): ?>
    <?php print $field->separator; ?>
  <?php endif; ?>

  <<?php print $field->inline_html;?> class="views-field-<?php print $field->class; ?>">
    <?php if ($field->label): ?>
      <label class="views-label-<?php print $field->class; ?>">
        <?php print $field->label; ?>:
      </label>
    <?php endif; ?>
      <?php
      // $field->element_type is either SPAN or DIV depending upon whether or not
      // the field is a 'block' element type or 'inline' element type.
      ?>
      <<?php print $field->element_type; ?> class="field-content"><?php print $field->content; ?></<?php print $field->element_type; ?>>
  </<?php print $field->inline_html;?>>
<?php endforeach; ?>

Now, what you'll eventually do is take the $id variable and print opening or closing tags based upon it's value. The $id variable represents the field that the view is currently printing.

So, right at the top, above the foreach(), insert a dpm statement so you can find the $id for your field. If you don't have the devel module enabled, install it or use a print_r statement instead.

<?php dpm(fields); ?>
<?php foreach ($fields as $id => $field): ?>
  <?php if (!empty($field->separator)): ?>
    <?php print $field->separator; ?>
  <?php endif; ?>
....

You'll see the names of your fields when you refresh the view. I want to group together the following fields:

$id are the names listed. So I will insert these two snippets of code:

  <?php if ($id == 'field_editors_value'): ?>
    </div>
  <?php endif; ?>

and

  <?php if ($id == title): ?>
    <div class="grouping_field">
  <?php endif; ?>

If you examine the code below you will see them in context.

<?php
// $Id: views-view-fields.tpl.php,v 1.6 2008/09/24 22:48:21 merlinofchaos Exp $
/**
 * @file views-view-fields.tpl.php
 * Default simple view template to all the fields as a row.
 *
 * - $view: The view in use.
 * - $fields: an array of $field objects. Each one contains:
 *   - $field->content: The output of the field.
 *   - $field->raw: The raw data for the field, if it exists. This is NOT output safe.
 *   - $field->class: The safe class id to use.
 *   - $field->handler: The Views field handler object controlling this field. Do not use
 *     var_export to dump this object, as it can't handle the recursion.
 *   - $field->inline: Whether or not the field should be inline.
 *   - $field->inline_html: either div or span based on the above flag.
 *   - $field->separator: an optional separator that may appear before a field.
 * - $row: The raw result object from the query, with all data it fetched.
 *
 * @ingroup views_templates
 */

?>
<?php dpm($fields);?>
<?php foreach ($fields as $id => $field): ?>
  <?php if ($id == title): ?>
    <div class="grouping_field">
  <?php endif; ?>
  <?php if (!empty($field->separator)): ?>
    <?php print $field->separator; ?>
  <?php endif; ?>
  <<?php print $field->inline_html;?> class="views-field-<?php print $field->class; ?>">
    <?php if ($field->label): ?>
      <label class="views-label-<?php print $field->class; ?>">
        <?php print $field->label; ?>:
      </label>
    <?php endif; ?>
      <?php
      // $field->element_type is either SPAN or DIV depending upon whether or not
      // the field is a 'block' element type or 'inline' element type.
      ?>
      <<?php print $field->element_type; ?> class="field-content"><?php print $field->content; ?></<?php print $field->element_type; ?>>
  </<?php print $field->inline_html;?>>
  <?php if ($id == 'field_editors_value'): ?>
    </div>
  <?php endif; ?>
<?php endforeach; ?>

Comments

Jolidog's picture

Hello, thanks for the nice tutorial.

You could also achieve the same result digging deeper into the views template system using, according to your example, views-view-field--title.tpl.php and views-view-field--editors-value.tpl.php

On the first insert the opening div tag, and on the second the closing tag.

Jeremy John's picture
Member since:
14 April 2010
Last activity:
2 days 7 hours

Hi Jolidog,

Thanks for the comment.

I have experimented with this technique, but views seems to filter divs in those field and will auto-close them, so they don't span across multiple fields.

Nicholai's picture

I've semi-achieved this result using Semantic Views. I group fields together using the rewrite output feature of views, and then apply a span or div wrapper to that field grouping with the semantic views plugin. It doesn't work for every situation, but you may want to check it out as an alternate approach.

mikeytown2's picture

I use http://drupal.org/project/views_customfield to output the 2 into a single field or do other things. I place the logic into a function inside a module. Easy to do IMHO. Use "Exclude from display" and here's some code to drop in so you can see whats available (everything above the "Customfield: PHP code" in your Fields).
http://drupal.org/node/732158

merlinofchaos's picture

Note that a brand new feature of Panels will allow you to do this just by applying the proper style, and no need of template munging at all. This will be in the 3.8 release of Panels. See http://www.angrydonuts.com/just-checked-a-new-feature-into-panels-3-dev for screenshots.

Obviously, it does require Panels.

Anonymous's picture

Another way to do accomplish the same thing is to add a Global: Custom text field and rewrite the output to include the values of all the fields you wish to group, then exclude those fields from display. It's not at all semantic, but it can be done without a template file or an additional module.

dalin's picture

This is definitely the way to go IMHO.

dsayswhat's picture

I tend to agree with this one - especially if you're building a site for clients who aren't HTML/PHP jockeys. Using .tpl files can have the effect of hiding important info from them...

On the other hand, if you don't know views very well, using custom fields might also hide the implementation details...but at least it's 'hidden' in a point and click environment.

Jeremy John's picture
Member since:
14 April 2010
Last activity:
2 days 7 hours

Hey thanks!

I had not realized that this technique existed. Everytime I had tried to put unclosing markup into custom fields views filtered and auto-closed it.

But I tested this and it works. I added a note above.

Anonymous's picture

how you summarized it up in the edit is interesting, but not what I had in mind. Think of it more like a field group in CCK; if the point is to be able to group arbitrary fields inside a DIV, include the values of those fields inside a "Global: Custom text" field. That entire Custom text field becomes the containing DIV.

Anonymous's picture

marvelous !

miaoulafrite's picture

hey, i successfully implemented it for block views. but it seems to be unavailable for page views?

Pooch's picture

Something else you may want to consider to accomplish this. If you want to basically mimic your node display you can create a CCK Group in the Manage Fields section for the node and then switch the Row style for the view to "Node" instead of fields. Granted this only works if you want your view to display the same as your individual node, but you have better control of grouping and ordering through the manage fields page on the node.