8

I've actually reached the bottom of Google trying to figure out how to add a css class to each row of a view. The trick is that I need the class for each row to be dynamically determined based on some of the data from the node that the view pulls from. The function that pulls this off neatly for the node is -

function pgc_preprocess(&$variables) {
  $node = $variables['node'];
  if ($node->type == "event") {
    $variables['event_class'] = '';
    $num_trainers = $node->field_number_of_trainers[0]['value'];
    $count = count($node->field_trainer);
    if($count < $num_trainers) {
        $variables['event_class'] = 'red';
    } else {
        $variables['event_class'] = 'green';
    }
    return $variables;
  }
}

The point of this is to color code an event that hasn't had enough folks sign up. There will be a list of events on the front page, and I need them to be color coded also. I really hope there some simple solution along the lines of -

function pgc_preprocess_views_view_unformatted(&$variables) {
  // Magic here, preferably having something to 
  // do with the function I already wrote.
}

Just dropping <?php print $event_class ?> in the view .tpl doesn't do it.

  • It may not be considered good practice (putting php logic in a tpl) but what about putting this directly in the row tpl ? – tostinni May 19 '11 at 0:44
  • 1
    that's not a CSS class, that's HTML. And it's supposed to be semantic. Try using meaningful classes and leaving red/green for the CSS. – Capi Etheriel Aug 1 '12 at 17:14
10
function pgc_preprocess_views_view_unformatted__home_listing(&$vars) {
  // Borrowed this bit from http://drupal.org/node/312220
  $view = $vars['view'];
  $rows = $vars['rows'];

  foreach ($rows as $id => $row) {
    $data = $view->result[$id];
    $event_class = get_the_classes($data->nid);
    $vars['classes'][$id] .= ' ' . $event_class;
  }
}

function get_the_classes($nid) {
  $node = node_load($nid);
  global $user;
  if ($user->uid != 0) { // Not for anon users.
    $event_class = '';
    if ($node->field_trainer[0]['uid'] == NULL) {
        $event_class= 'red';
    } else {
        $num_trainers = $node->field_number_of_trainers[0]['value'];
        $count = count($node->field_trainer);
        if($count < $num_trainers) {
            $event_class = 'red';
        } else {
            $event_class = 'green';
        }
    }
    return $event_class;
  }
}

Don't know if it's pretty. Don't know how it performs. But it works.

EDIT (02-01-2012): after working with Drupal for another year now, I'd have tried to find some other way to do this besides running node_load() on every row of the view.

  • 5
    note: in the template_preprocess_views_view method, you can access the node/entity data at $view->result[$id]->_field_data['nid']['entity'] (thus avoiding node_load() on each row) – g10 Aug 1 '12 at 16:19
0

your solution is great! To make sure that the classes will be really added to the views row classes you should add

$vars['classes_array'][$id] = implode(' ', $vars['classes'][$id]);

after

$vars['classes'][$id][] = $event_class;

And the preprocess function will be:

function pgc_preprocess_views_view_unformatted__home_listing(&$vars) {
  // Borrowed this bit from http://drupal.org/node/312220
  $view = $vars['view'];
  $rows = $vars['rows'];

  foreach ($rows as $id => $row) {
    $data = $view->result[$id];
    $event_class = get_the_classes($data->nid);
    if($event_class != '') {
        $vars['classes'][$id][] = $event_class;
        $vars['classes_array'][$id] = implode(' ', $vars['classes'][$id]);
    }
  }

}

Not the answer you're looking for? Browse other questions tagged or ask your own question.