4

I understand using Views you can use a different view mode, e.g. teaser or full content.

Is it possible to view a node using a view mode other than the full content view mode? What I want to achieve is being able to display different fields depending on the user's role.

6

You can override the page callback used on a node page to use your own function that will select the view mode based on the current user role.

/**
 * Implements hook_menu_alter().
 */
function MODULE_menu_alter(&$items) {
   $items['node/%node']['page callback'] = 'MODULE_node_page_view';
}

/**
 * Copy of the original node_page_view to use result from our
 * MODULE_node_show($node) as return value.
 */
function MODULE_node_page_view($node) {
  global $user;
  // If there is a menu link to this node, the link becomes the last part
  // of the active trail, and the link name becomes the page title.
  // Thus, we must explicitly set the page title to be the node title.
  drupal_set_title($node->title);
  $uri = entity_uri('node', $node);
  // Set the node path as the canonical URL to prevent duplicate content.
  drupal_add_html_head_link(array('rel' => 'canonical', 'href' => url($uri['path'], $uri['options'])), TRUE);
  // Set the non-aliased path as a default shortlink.
  drupal_add_html_head_link(array('rel' => 'shortlink', 'href' => url($uri['path'], array_merge($uri['options'], array('alias' => TRUE)))), TRUE);
  return MODULE_node_show($node);
}


/**
 * Copy of the original node_page_view to use result from our
 * MODULE_node_show($node) as return value.
 */
function MODULE_node_show($node, $message = FALSE) {
  if ($message) {
    drupal_set_title(t('Revision of %title from %date', array('%title' => $node->title, '%date' => format_date($node->revision_timestamp))), PASS_THROUGH);
  }

  $view_mode = MODULE_user_node_view_mode($node, $user); 

  // For markup consistency with other pages, use node_view_multiple() rather than node_view().
  $nodes = node_view_multiple(array($node->nid => $node), $view_mode);

  // Update the history table, stating that this user viewed this node.
  node_tag_new($node);

  return $nodes;
}

/**
 * Determines the view mode to use for the node page of the given node
 * when viewed by the given user.
 * @param $node
 *  The viewed node object
 * @param $account
 *  The viewing user object
 */
function MODULE_user_node_view_mode($node, $account) {
  // ... Implement your custom view mode selection logic here
}

Note: There is probably something that need to be done to ensure the page using a given view mode is not cached and re-used for different user.

  • Nice answer. How would I go for the same behavior but based on a path pattern with an additional item? Like node/%node/something? In case you have an idea my question is here: drupal.stackexchange.com/questions/194723/… In my case, "something" would be the view mode to use... – MrUpsidown Mar 15 '16 at 11:02
  • It's much easier now with hook_entity_view_mode_alter. Added answer below. – leymannx Jul 27 '18 at 21:59
2

For Drupal 6 have a look at Display suite and related modules, it allows you to easily define new build modes you can use in views. There's a similar project called Buildmodes.

2

For simple node display you can use Display suite to change the teaser and Default view modes as you want: You don't have to create a new one. If you want to create a new view mode in Drupal 7 you can use the Entity view modes module. Then you can change the view mode with Display Suite and use it in Views or in Field Boxes.

2

contextual_view_modes is another option which uses an active context to switch view modes - https://drupal.org/project/contextual_view_modes

From project page:

Ever wanted to change the view mode for a node based off of a context? Now you can. Contextual view modes adds a vertical tab where you can select a context to validate against and display a particular view mode. There is also a global content type option where you can view mode switch by context for every node of that content type.

1

I found a way that works for me, which is to create a new content type, and add a node reference field.
I can then reference the node I want, and using the Node Renderer, display it with the view mode I want.

1

You can simply use hook_entity_view_mode_alter() for that.

Change the view mode of an entity that is being displayed.

Here I change the view mode depending on a user's role:

/**
 * Implements hook_entity_view_mode_alter().
 */
function MYMODULE_entity_view_mode_alter(&$view_mode, $context) {
  if (!user_is_anonymous() && $context['entity_type'] == 'node' && $context['entity']->type == 'MYCONTENTTYPE') {
    $view_mode = 'MYVIEWMODE';
  }
}

To easily register your own view mode in the same module, simply implement hook_entity_info_alter. After that, place your fields and then trigger the switch from the hook above.

/**
 * Implements hook_entity_info_alter().
 */
function MYMODULE_entity_info_alter(&$entity_info) {
  $entity_info['node']['view modes']['MYVIEWMODE'] = array(
    'label' => t('My View Mode'),
    'custom settings' => TRUE,
  );
}
0

In all modes you'll have the $node object, or at least the node ID that allows you to load the node object.
You can show the node as you want, exactly like you do with node.tpl.php.

Also, Views has its own node-view.tpl.php for each view, so you can show it as you want, on teaser and full mode.

And to answer your question, except if (and I'm not sure) another module add mode, you've only teaser and full mode.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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