Views - Add a wrapper around fields or rows

by Jack-PL   Last Updated January 10, 2018 12:07 PM

Example:

I have a view with fields:

[field_name]    == Field collection item: Name
[field_title]   == Field collection item: Title
[field_text]    == Field collection item: Text

I can wrap these fields by excluding from display first two of them, and rewriting the output of the third field with tokens, for example:

<div class="span4">
    <div class="some_style">
        <blockquote>[field_text]</blockquote>
        <h5>[field_name] // [field_title]</h5>
    </div>
</div>

It seems a bit tricky, so here is my first question:

Is there any module or just another way to wrap fields in views?

I know Semantic Views module which solve the problem, but there is no recommended releases for Drupal 7.

Question #2

All my fields are wrapped in their div like in above mentioned example, but this is only the one row, and I have several rows. I need wrap all of them in another div.

Do I have to create a view template file only for that? which contain for example:

<?php if($rows): ?>
    <div class="rows">
        <?php print $rows; ?>
    </div>
<?php endif; ?>

I have a feeling like I miss something when I have to create a special template file only for one wrapper.



Answers 8


You can use views field or row templates but you will need to create template for every field.

May be this page will help you. Here is the sample code:

<?php
/**
  * Generic preprocess that is still working on D7
  */
function MYTHEME_preprocess_views_view_fields(&$vars) {
  if (isset($vars['view']->name)) {
    $function = __FUNCTION__ . '__' . $vars['view']->name . '__' . $vars['view']->current_display;

    if (function_exists($function)) {
     $function($vars);
    }
  }
}

/**
  * Then the specific preprocess that worked without the above code for D6
  */
function MYTHEME_preprocess_views_view_fields__VIEWNAME__DISPLAY(&$vars) {
  // my specific preprocess code
}
?>

Related: Specific preprocess functions for theme hook suggestions are not invoked at Drupal.org

smile
smile
May 02, 2013 20:34 PM

I think it's pretty safe to say that most people tackle both of your questions using the Cascading features of CSS.

For example, a typical view's HTML looks somewhat like this:

<div class="view view-NAME view-id-VIEWID view-display-id-VIEW-DISPLAY-id">
  <div class="view-content">
    <div class="views-row views-row-1 views-row-odd views-row-first">
      <div class="views-field views-field-FIELDNAME1">
        <span class="field-content">
           <!-- field content here -->
        </span>
      </div>
      <div class="views-field views-field-FIELDNAME2">
        <span class="field-content">
           <!-- field content here -->
        </span>
      </div>
    </div>
    <div class="views-row views-row-2 views-row-even">
     <!-- etc etc etc -->
    </div>
  </div>
</div>

So, to your 1st question, Views already creates a div that wraps each row, that's the <div class="views-row ..."> one. You can style it per view by doing something like this:

.view-NAME .views-row {
  /* styles for the rows div goes here */
}

And to your 2nd question, Views also already creates a <div> that wraps all the rows, that's the <div class="view-content"> one. To style it for a particular view you can do something like this:

.view-NAME .view-content {
  /* styles for the div wrapping your rows goes here */
}

Now, somewhat obviously, this is all dependent upon your theme. I am aware that some out there dislike all the markup Drupal by default creates and has overridden a lot of the standard templates to create leaner markup.

If that's the case in your instance, you should still be to instruct Views to add a class to each row if you want. This is accessed via the overall Style Settings (where you can also look at each Views template that is used for the particular view).

You could also instruct Views to add a class to each field wrapper. This is accessed from the config widget by each field.

ADDITION based upon commentary:

The Views template that creates the output of the view-content div is views-view.tpl.php and the code in question is:

<?php if ($rows): ?>
  <div class="view-content">
    <?php print $rows; ?>
  </div>
<?php elseif ($empty): ?>
  <div class="view-empty">
    <?php print $empty; ?>
  </div>
<?php endif; ?>

so without changing this up, you're right, Views doesn't allow quick and easy preprocessing of the View to insert any other variables into that div's classes.

You could however use Views' preprocessing hooks to create an additional variable so you don't need to create lots of additional templates but rather just one more.

For example, copy views-view.tpl.php to your theme (easiest) or module (requires special Views theme incantations :) and modify it along these lines:

<?php if ($rows): ?>
  <div class="view-content <?php print $my_special_content_class; ?>">
    <?php print $rows; ?>
  </div>
<?php elseif ($empty): ?>
  <div class="view-empty">
    <?php print $empty; ?>
  </div>
<?php endif; ?>

and then create a views preprocess hook along these lines:

function YOURTHEMEORMODULE_preprocess_views_view(&$vars) {

  $name=$vars['name'];
  $display_id=$vars['display_id'];

  if ($name=='VIEWYOUWANT' && $display_id=='DISPLAYYOUWANT') {
    $vars['my_special_content_class']='FOO';
  } else {
    $vars['my_special_content_class']=''; // so we don't have to isset() or !empty() it in our template :)
  }

}

Save everything and clear your theme cache and now you should be on your way.

SECOND ADDITION:

Upon further thought, and a 'doh!' moment, you can do this without a template at all in preprocess like this:

function YOURTHEME_preprocess_views_view(&$vars) {

  $name=$vars['name'];
  $display_id=$vars['display_id'];

  if ($name=='VIEWYOUWANT' && $display_id=='DISPLAYYOUWANT') {
    $vars['rows']='<div class="FOO">' . $vars['rows'] . '</div>';
  }

}

if you don't mind another wrapped div in there. And, I think you will need to/should do this in your theme instead of a module so you make sure this happens in the right order, eg, you want this to happen after Views is all said and done with things, and the theme hooks always run after the module hooks.

Jimajamma
Jimajamma
May 03, 2013 01:36 AM

You could also use the rewrite feature inside the view.

Assuming you have field_name, field_title and field_text and you would like to add a div with a class called content around these:

  1. In the view under FIELDS click on field_name
  2. Scroll down to REWRITE RESULTS and check Rewrite the output of this field
  3. In the text box that appears, fill in something like <div class="content">[field_name] NOTICE that you don't should close the div
  4. Save the field
  5. Under FIELDS click on field_text
  6. Scroll down to REWRITE RESULTS and check Rewrite the output of this field
  7. In the text box that appears, enter </div> THIS CLOSES THE CONTENT DIV
  8. Save you field

I guess the above will not always work depending on what kind of wrapper elements your field have.

Cyclonecode
Cyclonecode
November 14, 2013 23:37 PM

You can use Drupal 7 Field Formatter CSS Class Module.

The Field formatter CSS class module allows you to set any text/list/option/taxonomy field to render as CSS class on the node. This enables the node author to select predefined CSS styling per node.

user3127890
user3127890
March 18, 2014 23:46 PM

You can also use Semantic Views.

This Views plugin makes unformatted styles, field row styles and other output more readily configurable without needing to override template files. Instead of overriding row style templates for views where you want to specify different HTML elements (tags) and class attributes, you can specify these inside the Views UI and avoid overriding templates for each view.

Sunil
Sunil
November 27, 2015 09:28 AM

To preprocess field_collections and override output, try the following example found on dropbucket which give you some handy snippet by @dane:

function mytheme_preprocess_field(&$vars) {
  if($vars['element']['#field_name'] == "field_your_fc_field"){
    $fcs = array();
    foreach (element_children($vars['element']) as $key) {
      $fcs[] = array_pop($vars['element'][$key]['entity']['field_collection_item']);
    }
    // now you have all your fcs pulled out of that nasty array
    foreach ($fcs as $fc) {
      # code... that 
    }

    // I would recommend overrideing items markup for whatever black magic you desire
    $vars['items'] = array(
      '#markup' => "Whatever you need to render",
    );  
  }
}
kenorb
kenorb
April 04, 2016 23:36 PM

To add a wrapper to fields such as field collection, you should define the logic in hook_preprocess_HOOK (where HOOK can be views_view_field), then expose these variables into template file, for example:

/**
 * Implements hook_preprocess_HOOK().
 */
function MYMODULE_preprocess_views_view_field(&$vars) {
  $view = $vars['view'];
  switch ($view->name) {
    case 'my_view':
      $node = entity_metadata_wrapper('node', $vars['row']->nid);
      $vars['name']  = $node->field_name->value();
      $vars['title'] = $node->field_title->value();
      $vars['text']  = $node->field_text->value();
    break;
  } // end: switch
}

So now you can use these variables inside the template file ($name, $title and $text), so you can wrap it easily.

kenorb
kenorb
April 04, 2016 23:45 PM

Try Views Rows Wrapper module. It wraps every N rows with Div/Span element with custom class or id name.

JetSet
JetSet
January 10, 2018 11:54 AM

Related Questions