I was wondering how to specify a specific template for rendering a node when it's referenced from another content type.
For example I have a content-type (product) and I use the node--product.tpl.php
template to render nodes of this type. Then I have a content-type named container
that have a node reference
field that may related a number of product
nodes.
I would like to use a different template when rendering a product
when the product is referenced from the container
content-type.
I just installed the theme developer
module and check suggested templates, I then created a new template named node-reference--product.tpl.php
in the same folder as node--product.tpl.php
but this file is only used if node--product.tpl.php
is removed.
I guess one approach would be to use some kind of theme_preprocess
hook and load a node based on the arg(1)
value and then check if the type is container
and if it is add a template suggestion in the $variables
parameter.
2 Answers
The simplest thing you can do is provide a new "View Mode" for nodes, so that you can use it with the "Rendered Node" display option for the node reference field.
This would be done in a small custom module using hook_entity_info_alter()
like so:
function MYMODULE_entity_info_alter(&$info) {
$info['node']['view modes']['node_reference_product'] = array(
'label' => 'Node Reference Product',
'custom settings' => TRUE
);
}
Once the module is installed you'll have a new view mode under the "Rendered Node" display format options:
Now you can simply use the same node--product.tpl.php
template file as normal and just test for the view mode to define what you want to display:
<?php if ($view_mode == 'full') : ?>
<!-- HTML output for the full view mode -->
<?php elseif ($view_mode == 'teaser') : ?>
<!-- HTML output for the teaser view mode -->
<?php elseif ($view_mode == 'node_reference_product') : ?>
<!-- HTML output for your new view mode -->
<?php endif; ?>
Of course you still have access to the view mode in any hook_preprocess_node
function so you could put your logic in there instead:
function MYTHEME_preprocess_node(&$vars) {
if ($vars['view_mode'] == 'product_node_reference') {
$vars['content'] = array('#markup' => 'Some other content');
}
}
But perhaps the best part of solving your problem this way is that Drupal honours the new view mode in the UI, so for each content type you will now have a new view mode which you can choose options for as normal:
Just like the standard full
and teaser
view modes you will be able to decide which fields are displayed, and the ordering and format in which they are displayed too. It's entirely possible that after writing that tiny one-function module you won't need to write another line of code to solve the problem.
You'll also have this view mode available system wide for use in, for example, Views/Panels etc.
-
I created a module that included
hook_entity_info_alter()
and set theRender Node
view mode toNode Product Reference
for the reference field in thecontainer
content-type, but the view_mode for all nodes were still set to full, why is that? I managed to solve the problem usinghook_preprocess_node()
in wich I forcefully set the view_mode to the correct value. Commented Feb 27, 2012 at 11:35 -
I'm not sure to be honest, I used the exact code in the answer above and it worked fine for me :/– Clive ♦Commented Feb 27, 2012 at 11:38
-
I was thinking that it could be because the field already contained references when it changed the view mode. Anyway - Thanks alot for your nice answer=) Commented Feb 27, 2012 at 11:43
-
1
It might be simplest to create a different field formatter for the entity reference on the container node. Instead of the default "Title(link)" or "Rendered Node" you can add one and theme it however you would theme the separate node templete you were trying to theme. See a writeup here: http://www.computerminds.co.uk/articles/creating-new-field-formatters-drupal-7 . In your hook_theme() you could specify a template instead of a function. I would choose this over creating a check in theme_preprocess() as it is easier to manipulate if you want to change it in the future.
I might also check out the Display Suite module if you haven't yet which will allow you to move parts of the node around in the content type settings form. It has some similar features to Panels but is much more lightweight. It might save you from creating separate node templates at all.