I can use view mode template suggestions only after I specify content type, eg: node--contenttype--viewmode.tpl.php . I am trying to use node templates per view mode for all content types, eg: node--viewmode.tpl.php but with no results.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

lukpe’s picture

OK, I'm not a dev, but if anyone is looking for this kind of functionality, here is a solution - replace function entity_view_mode_preprocess with this code (exclulding opening and closing php tags):

<?php



/**
 * Implements hook_preprocess().
 *
 * Add template suggestions for an entity based on view modes if they do not
 * already exist.
 *
 * The eventual order of the entity's theme suggestions are:
 * - entity-type__bundle
 * - entity-type__bundle__view-mode
 * - entity-type__id
 * - entity-type__id__view-mode
 * - entity-type__view-mode
 */
function entity_view_mode_preprocess(&$variables, $hook) {
  // @todo Improve checking of entity type based on hook. Some entities do not
  // match 1:1 like file_entity and user_profile.
  if (!empty($variables[$hook]) && !empty($variables['theme_hook_suggestions']) && entity_get_info($hook)) {
    $view_mode = $variables['elements']['#view_mode'];

    $entity_type = $hook;
    $entity = $variables[$entity_type];
    list($id, , $bundle) = entity_extract_ids($entity_type, $entity);

    $suggestions = &$variables['theme_hook_suggestions'];

    // Ensure the base suggestions exist and if not, add them.
    if (!in_array("{$entity_type}__{$bundle}", $suggestions)) {
      // The entity-type__bundle suggestion is typically "first".
      array_unshift($suggestions, "{$entity_type}__{$bundle}");
    }
    if (!in_array("{$entity_type}__{$id}", $suggestions)) {
      // The entity-type__id suggestion is always "last".
      array_push($suggestions, "{$entity_type}__{$id}");
    }
	
    // Add view mode suggestions based on the location of the base suggestions.
    if (!in_array("{$entity_type}__{$bundle}__{$view_mode}", $suggestions)) {
      $index = array_search("{$entity_type}__{$bundle}__{$view_mode}", $suggestions);
      array_splice($suggestions, $index + 1, 0, "{$entity_type}__{$bundle}__{$view_mode}");
    }
    if (!in_array("{$entity_type}__{$id}__{$view_mode}", $suggestions)) {
      $index = array_search("{$entity_type}__{$id}", $suggestions);
      array_splice($suggestions, $index + 1, 0, "{$entity_type}__{$id}__{$view_mode}");
    }
	
	// Add view mode suggestions based on entity type.
	array_splice($suggestions, $index + 1, 0, "{$entity_type}__{$view_mode}");
  }
}



?>

Last line implements/hacks in functionality I was looking for.

PS. Sorry but I don't know how to create patch (yet).

lance.gliser’s picture

Category: bug » feature

I would also like to target just the node and view type at times. I got around it by adding only:

    if (!in_array("{$entity_type}__{$view_mode}", $suggestions)) {
      $index = array_search("{$entity_type}__{$view_mode}", $suggestions);
      array_splice($suggestions, $index + 1, 0, "{$entity_type}__{$view_mode}");
    }

to the preprocess function.

Manuel Garcia’s picture

Status: Active » Needs review
FileSize
1.02 KB

This would indeed be nice to have, so as to reuse the same template for different bundles.

Find attached the patch based on #1 & #2

Anonymous’s picture

The code in #2 is broken. After checking for the existence of that value in the array, it searches for that value again. This has the effect of always adding the suggestion in the same place. There's a patch that addresses this bug as it already exists in the module. #1831766

I've rewritten the patch in #3 to apply on the current dev release. It also adds the {$entity_type}__{$view_mode} suggestion as the lowest priority, so it shouldn't disrupt existing themes that depend on the order provided by this function.

JurriaanRoelofs’s picture

Status: Needs review » Reviewed & tested by the community

Test 4 works well. Minor note: patch file name should start with project name.

Dave Reid’s picture

My question is since both view mode and bundle are strings, how can we prevent collisions when both view mode and bundle are the same string? I'm not sure how useful a template for an entity type and view mode but is bundle-agnostic since by nature view modes are very bundle specific for their configuration and don't share anything between different bundles.

Dave Reid’s picture

Status: Reviewed & tested by the community » Needs review
JurriaanRoelofs’s picture

since by nature view modes are very bundle specific for their configuration and don't share anything between different bundles.

This is not the case if you embrace view modes as a first class citizen in your application, view modes are an excellent analogy to design patterns of well crafted application designs.

I think the best way to prevent collision is to add a not in the project page and README, there are more points in Drupal where you just give stuff the same name so I think it's a best practice.

Anonymous’s picture

My question is since both view mode and bundle are strings, how can we prevent collisions when both view mode and bundle are the same string? I'm not sure how useful a template for an entity type and view mode but is bundle-agnostic since by nature view modes are very bundle specific for their configuration and don't share anything between different bundles.

I have a view mode called "slide" which is how nodes are formatted when they appear in a jQuery Cycle slideshow. My theme suggests a theme as 'node__slide' which causes Drupal to use node--slide.tpl.php.

This template prints specific variables including from $content for fields. Actually it's just a "main image" field, which almost every content type will have.

We cannot prevent collisions, but collisions can be managed with either with more specific templates to handle the conditions where the wrong template is selected or the theme's hook_preprocess_node function can override or force the theme_hook_suggestion(s).

I do think it's a potential problem because of the abundance of bundles and view modes for nodes. Someone might create a "teaser" or "print" content type. (Or "slide," which I've done, and the collision was perfectly acceptable!)

I've almost convinced myself that this kind of unpredictability isn't worth it. The right way to do this is to implement this in your theme:

function THEME_preprocess_node(&$variables, $hook) {
  if ($variables['view_mode'] == 'slide') {
    $variables['theme_hook_suggestion'] = 'node__slide';
  }
}

or even:

function THEME_preprocess_node(&$variables, $hook) {
  $variables['theme_hook_suggestion'] = 'node__'. $variables['view_mode'];
}
Dave Reid’s picture

Should we mark this as won't fix then?

Anonymous’s picture

Status: Needs review » Fixed

Yep.

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.

goldenboy’s picture

Status: Closed (fixed) » Needs review

Status: Needs review » Needs work

The last submitted patch, 4: template_suggestion_view_modes-1300818-4.patch, failed testing.

eelkeblok’s picture

Issue summary: View changes
Status: Needs work » Closed (won't fix)

The reason to close this as won't fix seems to be well thought-out. When re-opening (by supplying new versions of the patch or otherwise), please also give clear motivation why you still feel this needs to be added to this module.