Skip to: Site menu | Main content

Using theme overrides

As long as I'm being sidetracked and/or feeling inspired to write, here's another quick entry. This one gives a brief introduction to hook_theme and theme overrides.

This particular use case involves changing how CCK's node reference displays its output. I had created a content type that utilized the nodereference field type to attach different stories to a newsletter. So, in this case, I wanted more than just the linked "Title" of the referenced node to appear. Fortunately, CCK is smart/kind enough to make use of hook_theme (in nodereference.module) as follows:
function nodereference_theme() {
return array(
'nodereference_select' => array(
'arguments' => array('element' => NULL),
),
'nodereference_buttons' => array(
'arguments' => array('element' => NULL),
),
'nodereference_autocomplete' => array(
'arguments' => array('element' => NULL),
),
'nodereference_formatter_default' => array(
'arguments' => array('element'),
),
'nodereference_formatter_plain' => array(
'arguments' => array('element'),
),
'nodereference_formatter_full' => array(
'arguments' => array('element'),
'function' => 'theme_nodereference_formatter_full_teaser',
),
'nodereference_formatter_teaser' => array(
'arguments' => array('element'),
'function' => 'theme_nodereference_formatter_full_teaser',
),
);
}

The piece I cared about was the nodereference_formatter_default argument (because I had set the Display for that content type to use the Default). I copied
/**
* Theme function for 'default' nodereference field formatter.
*/
function theme_nodereference_formatter_default($element) {
$output = '';
if (!empty($element['#item']['nid']) && is_numeric($element['#item']['nid']) && ($title = _nodereference_titles($element['#item']['nid']))) {
$output = l($title, 'node/'. $element['#item']['nid']);
}
return $output;
}

from nodereference.module into my template.php file and renamed it mytheme_nodereference_formatter_default (where mytheme is the actual theme name). Then I added a bit of logic after $output = l($title, 'node/'. $element['#item']['nid']); (inside of the if statement) to append some more information to the $output string.

Easy as pie, right? No need to "hack" anything!

Thanks for your reactivity !

Thanks for your reactivity ! Very impressive !

To answer your question, I selected "Full node" but it is the same with "Teaser".

But if I select "Title" or "Title with link" the "theme_nodereference_formatter_default" or "theme_nodereference_formatter_plain" are correctly overridden.

I'm not a Drupal expert but I'm suspecting "nodereference_formatter_full_teaser" is not passed through the theme() function ... see the "nodereference_theme()" function... What do you think ?

Thanks for your help... when you have some time.

theme_nodereference_formatter_full_teaser

I've taken a look at the function and one thing I see is that it is considered a "proxy" function (according to the comment above the function). I don't know if this makes a difference. It does ultimately return the $output variable.

Have you copied the entire function and made your changes to the $output variable inside of the appropriate if statement?

Well, the problem is more

Well, the problem is more that the themed function is not triggered at all:
- I copied the function into my template.php exactly as it is in the nodereference.module file
- I renamed it "mythemeName_nodereference_formatter_full_teaser"
- I tried to modify the $output variable, but finally ended to just add a print "hello" to see if it is called ...
and nothing...

(again this process applied to "theme_nodereference_formatter_default" or "theme_nodereference_formatter_plain" is working well ...)

I'm beginning to see what the issue is

Here is where I am seeing the problem is coming in. According to nodereference_theme() the hook is nodereference_formatter_full or nodereference_formatter_teaser. But, you can see that the 'function' being called is actually theme_nodereference_formatter_full_teaser. So, there isn't actually a theme_nodereference_formatter_full or theme_nodereference_formatter_teaser to override.

I have tried doing the override in template.php via mytheme_nodereference_formatter_full and mytheme_nodereference_formatter_teaser. I have also tried mytheme_theme_nodereference_formatter_full_teaser as well as mytheme_nodereference_formatter_full_teaser. None of those functions is being triggered. Surely, there must be a way to create a theme override or there is no point in specifying those functions in nodereference_theme.

I have filed a support request in the issue queue.

In the meantime can you do the override to the default or plain functions?

Yes, the overriden of default

Yes, the overriden of default or plain function is working.
It seems the way the hook theme are defined for full node and teaser formater does not allow to theme "theme_nodereference_formatter_full_teaser" but I'm not drupal expert enough to know why and how to fix it...

I posted also a request in a alredy existing issue related to the use of node reference formaters : http://drupal.org/node/483646

Let's see if somebody can figure out what is going wrong...
Thanks anyway for your help.

Use default or plain for the time being

I understand that the default and plain functions are able to be overridden. What I meant by my question was whether you could accomplish the override you want to do by using either default or plain instead of teaser or full. Why are you trying to override those?

I use node_reference to

I use node_reference to include a node within another, and the content of the referenced node is displayed fully and directly within the node that include the reference, not only a link to the node. In "admin/content/node-type/fiche-projet/display/basic" I choose to display the node_reference field as "full node" instead of "title" or "title with link".
So, this is not "theme_nodereference_formatter_plain" nor "theme_nodereference_formatter_default" that is triggered but indeed "theme_nodereference_formatter_full_teaser".

You can still choose default or plain

If you choose the default or plain and override it, then you can add whatever additional information you want to make it look like the full view.

Override "theme_nodereference_formatter_full_teaser" ?

I tried to do the same with "theme_nodereference_formatter_full_teaser"as the node references are displayed as full nodes in my case, but no way to override it ! Do you know if there is a reason why it doesn't work ?
(override "theme_nodereference_formatter_default" or "theme_nodereference_formatter_plain" is working !)
Thanks

RE: override theme_nodereference_formatter_full_teaser

Give me a chance to see when I can make some time to play with this. I don't see why this should work any differently.

The only thing that I can think to ask off the top of my head is how you have set the Display Field for that piece of content (admin/content/node-type/your-node-type/display). Have you selected "Teaser" under the Teaser and/or Full node views?

Credits: XWeb | Chris Herberte | Andreas Viklund