Drupal 6 Views Templates

22nd March 2011 - 14 minutes read time

Rewriting the output of a Drupal view isn't always necessary, but figuring out what to do with the available templates can very useful. It is, however, also a bit of a stumbling block from time to time, especially for newcommers. After you have created your view you will have a number of filters to restrict your data, and a set of fields which are printed by Views using a set of templates. How these templates are used depends on what sort of view data you use and style you select, but there will be three standard templates that are always used in views. These templates are display, style and row and can be treated like any other Drupal template in that you can override them with more specific filenames.

Display output
This is the top level views template and is used by the block, page and attachment view types. The purpose of this template is to render everything that surrounds the view itself, which would be administration links, pagination, headings and footers. The default teplate in use here is views-view.tpl.php, which can be overridden in the following ways.

views-view.tpl.php
views-view--{view name}.tpl.php
views-view--{display type}.tpl.php
views-view--{view name}--page.tpl.php
views-view--{view tag}.tpl.php
views-view--{display type}-{display ID}.tpl.php
views-view--{view name}--{display ID}.tpl.php

For example, a page display type in a view called MyView, the default template views-views.tpl.php would be overridden by a more specific file called views-view--myview--page_1.tpl.php.

Style output
This template directly surrounds the view and is used to setup things like tables, lists or select elements. A loop is also included in this template to print out the data and any surrounding elements like an li element in a list. Each data item is called a row, the actual row data printing is passed onto another template file. The default template in use here is views-view-{style}.tpl.php, where style is the style selected from the views options. This is either be grid, HTML list (list in the template filename), jump menu (menu in the template filename), table and unformatted (which is the default). Changing the style of your view will change the name of the file being included. The default template can be overridden in the following ways.

views-view-{style}.tpl.php
views-view-{style}--{view name}.tpl.php
views-view-{style}--{display type}.tpl.php
views-view-{style}--{view name}--page.tpl.php
views-view-{style}--{view tag}.tpl.php
views-view-{style}--{display type}-{display ID}.tpl.php
views-view-{style}--{view name}--{display type}-{display ID}.tpl.php

Row style output
This template is used to print out the data itself, which depends on the row style that has been selected in the view. If you have used nodes as the data type when setting up the view then you can chose between fields and node. The fields style will print out any fields you have selected, whereas the node template will print out the node using the node.tpl.php template. The default template here is called views-view-{fields/row-node}.tpl.php, which can be overridden in the following ways.

views-view-{fields/row-node}.tpl.php
views-view-{fields/row-node}--{view name}.tpl.php
views-view-{fields/row-node}--{display type}.tpl.php
views-view-{fields/row-node}--{view name}--{display type}.tpl.php
views-view-{fields/row-node}--{view tag}.tpl.php
views-view-{fields/row-node}--{display type}-{display ID}.tpl.php
views-view-{fields/row-node}--{view name}--{display type}-{display ID}.tpl.php

To see the template filenames, go into the view editor and go into the display type you are looking at (eg Page) and select Theme from the left hand block of options.

The Drupal Views Admin Interface

The Drupal Views Admin Interface

 

Once you click on the Theme button you will see the following displayed at the bottom of the screen. The template files in bold are the currently selected templates being used in this view and display combination. As this is a default view with no template files, the default templates are highlighted.

Drupal Views Theme Administration Area

Drupal Views Theme Administration Area

To override any views template file you can copy the file from the theme directory in the views module into your theme and rename it if you want or leave it so that all views will pick up the same template file. You can also click on the name template type you want to override within the views theme admin interface, which will print out the code for the template so you can copy and paste it into a file.

To override any views template file you can copy the file from the theme directory in the views module into your theme and rename it if you want or leave it so that all views will pick up the same template file. You can also click on the name template type you want to override within the views theme admin interface, which will print out the code for the template so you can copy and paste it into a file.

There is a button at the bottom of the views theme admin interface called Rescan template files. If you add or remove any theme file you can click this button to get views to rescan your theme directory. This is the only action of this section and all it does it to rescan your current theme in order to discover views template files. Any new files it picks up and uses for the current view will be highlighted in bold. One good thing to note is that the administration theme has no impact on the views theme files.

Organising views files can be a bit of a problem, especially as many files are usually created as the site grows. To get around having large numbers of files in your theme directory (along with you block, node and page templates) you can create a subdirectory to store view template files. Views will be able to discover any files you place in there in the same way as normal so it is a great way of organising things. Here is my usual setup for a theme I am working on.

themes/
  mytheme/
    css/
    js/
    view_templates/ 
      views-view-fields--myview--block.tpl.php
  template.php
  mytheme.info

It is possible to override every single field of a view using a separate file for each field. This is built into the views theme system, and although it is powerful it can lead to the situation where you have hundreds of template files and difficulty in telling what field is being effected by what file. I often find it slightly easier from a maintenance point of view to do as much as I can within the view itself (ie, before templating happens) by rewriting the contents of fields and then use a single row template to control the output of the view fields.

If fields are selected as the display type then the default fields template is called view-view-fields.tpl.php and will print out each of the fields in turn. Views also adds a little bit of extra HTML and other formatting that you might not want. Below is the contents of the view-view-fields.tpl.php file.

<?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; ?>

The main problem here is trying to figure out what to put in the file and how to change the template code. I normally write code that will output every field in the correct place surrounded by the needed HTML. Especially if the template in question is quite specialized. This means deleting most of the default code and replacing it with direct calls to the field output. For example, the following will print out the title of a node found in a view.

<?php print $fields['title']->content; ?>

If you select the option to make the title of the node a link then the above template will print out the node title as a link. No extra templating is needed here.

The tricky bit here is converting the fields you add to your view into fields in your template. Normal Drupal fields like title and teaser are fine, but CCK fields will be altered to be called field_{cck field name}_value. There are also third party modules that will create views fields in different ways. You might think that you could just do this to figure out what is in the $fields variable to what is contains.

print_r($fields);

You will find, however, that this will print out lots and lots of information, most of which is irrelevant to what you are trying to do. Every item in the array contains both the data and a reference to the parent view object, which holds a lot of data.

The solution is to loop over each of the fields in the $fields array and figure out what fields exist in the data. This can be done using the following code.

<?php 
foreach ($fields as $fieldname => $fielddata) {
    print $fieldname . '<br />';
}

This will print out something like the following, but will depend on what fields you have in your data.

title
field_text_content
field_mycckfield_content

You can then use these values to print out your data on an individual basis like the following snippet.

<?php print '<h2 class="articletitle">' . $fields['title']->content . '</h2>'; 
print $fields['field_text_value']->content;
print $fields['field_mycckfield_value']->content;

Other strategies to print out data in a view fields file include keeping the default loop, but also using a switch statement. This might be useful if you want to retain the view fields ordering ability, but don't want to use the default view fields template mechanism. The following snippet will print out the same as the snippet above, but can be expanded with ease.

<?php 
foreach ($fields as $fieldname => $fielddata) {
    switch ($fieldname) {
        case 'title':
            print '<h2 class="articletitle">' . $fielddata->content . '</h2>';
            break;
        default:
            print $fielddata->content;
    }
}

Once you figure all this stuff out you still have to be aware that views will sit inside other Drupal components like blocks and pages and will therefore be subject to their template styles. They do not effect the views templates themselves, but you will find extra div elements surrounding your view that you might not have expected.

Figuring out what these surrounding templates are called is not too tricky, and they can be overridden in the same way as any other Drupal template. To find out what page templates are available add a call to the hook_preprocess_page() hook in your template.php file. Look out for the array item 'template_files'.

function myawesometheme_preprocess_page(&$vars) {
    echo '<pre>'.print_r($vars, true).'</pre>';
}

Views page templates will follow the convention page-{path}.tpl.php, but this can be changed in the above. To detect that we are looking at the view page and to change the template file to something else (in this case a file called page-myview.tpl.php) use the following code.

function myawesometheme_preprocess_page(&$vars) {
    if (!isset($vars['node'])) {
        $vars['template_files'] = array('page-myview');
    }
}

The same thing can be done with views that are displayed in a block, but in this case it is easier to override the template files as there are more choices available. To see what templates are available for a view then use the following snippet and look for the template_files array item.

function myawesometheme_preprocess_block(&$vars, $hook) {
    echo '<pre>'.print_r($vars).'</pre>'; 
}

The block template files follow the same format as they normally do, but here the names are a little different. To override all views block templates with the same template file use block-view.tpl.php, this is the normal Drupal way of naming block templates. To override a specific view block template use the format block-views-{viewname}-block_{block ID}.tpl.php. The block ID here is the id from the view itself and depends on the number of blocks created in a particular view.

Comments

Permalink

Nicely written! Very informative and will be handy on my next drupal project when I've forgotten all of this all over again

Ad (Tue, 03/22/2011 - 09:29)

Permalink

hi,

how to organize views_template directory in my theme directory and how to write _preprocess_page() function in template.php file.

i was little confused please help me.

regards,

pandikamal

pandikamal (Mon, 04/04/2011 - 13:33)

Permalink

With regards to the views_template directory you can just place your view templates in there and views will pick them up. You don't really need to organise beyond that.

The hook_preprocess_page() function needs to be called the same as your theme, so if your theme name is mytheme, then your function would be mytheme_preprocess_page(). Once this is in place then clearing your caches should get Drupal to pick it up. The idea behind that code is to override the elements that surround a view page if you didn't want to use the default page.tpl.php file.

Permalink

Hi,

Thanks for a great article. I would like to use a template override as per the Theme information displayed in the View editor. However, all articles I have read talk about placing the tpl.php files in a theme. But do I have to create an actual theme first? Can they be placed in my module directory instead, e.g. sites/all/modules/mymodule/mymodule-view-field.tpl.php or sites/all/modules/mymodule/templates/mymodule-view-field.tpl.php? I see that other modules have theme overrides in their module directory. Why doesn't it work when I "Rescan templates"? What I am I missing?

Any help would be much appreciated.

Best regards,
Kevin

Kevin (Fri, 05/20/2011 - 21:28)

Permalink

One how to question: is there a way to recognize the node type per row of table views and display different icon? For example, i would like to display announcement icon and treat its row differently (such as adding background color to tr and bold title of the announcement row) than the regular posts in the table views. I'm looking at views-view-table.tpl.php to do some changes with out success.

| Icon | Title
---------------------------
| P | This is a regular post
| A | This is an announcement
| P | This is a regular post

thanks in advance

Anonymous (Sat, 05/21/2011 - 19:30)

Permalink

 

You will need to add the node type into the view fields but exclude from output.

Look at the theme information section in views and then copy the code from style_output and create a new file in your theme called views-view-table.tpl.php (depending on how specific you want to get).

Then add a preprocess function in your template.php file like this. I am setting a class based on a cck field but it's no different for a node type:

function mytheme_preprocess_views_view_table(&$variables) {

// kpr($variables); << this will show you the structure so you know what to target - you need the devel module for this to work

  foreach ($variables['view']->result as $count => $result) {

    $node_level = $result->node_data_field_level_field_level_value;

    if ($node_level == 8) {

      $variables['classes'][$count] = $variables['classes'][$count] . ' gold';

    } elseif ($node_level == 5) {

      $variables['classes'][$count] = $variables['classes'][$count] . ' silver';

    } elseif ($node_level == 2) {

      $variables['classes'][$count] = $variables['classes'][$count] . ' bronze';

    }

  }

}

 

soulston (Sun, 06/05/2011 - 14:25)

Permalink

Hi, am a newbie and trying to create the functionality same like as being used at the following site whose url is http://www.hafeezcentre.pk/.

I want to create out and functionality same as under the main Heading FEATURED ADS on that site. Can anyone help me to write node.tpl.php to produce that functionality using view module. Waiting for response

methow (Tue, 03/20/2012 - 15:54)

Permalink

Yo need to do the following in your node template if you want a specific template just for the views.

if ($view instanceof View) {
  // View template
} else {
  // Non-view template
}
Permalink
While building a recent view I was attempting to use a DIV with some token replacements, I was rewriting the output of a field. I needed some fancy css to pull a CCK color field. Then I discovered that I really couldn't do this. Views will strip your DIVs when when your rewrite the output of a field. This drove me to a more complex solution, using a views template. (There's an interesting thread on drupal.org about the limitation I hit , node/853880) This writeup really helped me work through a proper solution, Big Thanks.

Slackstone McS… (Sat, 06/29/2013 - 00:12)

Permalink
i like drupal and plan to develop my next sites in drupal currently working on http://acom.pk and its in magento but i think drupal is powerful

king (Thu, 01/28/2016 - 14:34)

Add new comment

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