Hello,

I have made a CCK content type that has a node reference field in it. This field should look at a view that contains another CCK content type that has a title, an image and some description.
What I am trying to accomplish is have the node reference field display a list of titles (taken from the view) at edit time, but display an image (again from the view) at display time. Problem is that on field display settings I only have title,title as link, teaser, node as options. Any idea on how should I tackle this?

Comments

marcvangend’s picture

Similar question in http://drupal.org/node/358857

mxa055’s picture

Thanks a lot...

Just what I was looking for. I guess I can't search these forums as good as the pros :(

marcvangend’s picture

It sounds unfair, but I think you're right. Experienced Drupallers can probably search better, simply because they know the right search terms. Let me tell you what I searched for: "node reference formatter image". Want to know why?

When you add a CCK field to a content type, you have three choices to make. The first choice is the field type: text, integer, decimal, node reference etc. The second choice is the 'widget', or: how the field will look on the add-node form. For instance, a text field can appear as a single line input, a text area or a select box. The third choice is the 'formatter'. The formatter decides what the field will look like when the node is viewed. For instance, an image in an image field can be shown as image or presented as download. Once you know these terms, you can get better search results.

mxa055’s picture

Yes you are right I had no idea what it was called.

So if I am getting this correctly I have to make a new module that extends the nodereference module for CCK?
What are the files that I should alter beyond making a .module and .info file for the module extension?

marcvangend’s picture

Exactly, the best way would be to write a module that defines a new CCK formatter for the node reference field type. I just found a tutorial here: http://manueg.okkernoot.net/blog/200907/how-create-cck-formatter. I think you can copy-paste a lot of code from that tutorial.

A Drupal module exists of at least a .module file and .info file. For a simple module like this, you will not need other files. Besides those two files (placed in their own folder), you don't have to alter anything.

In case you're thinking "If I don't alter other files, how would CCK know about my module?": that is how Drupal hooks work. When a module "implements a hook", it will respond when that hook is invoked. The tutorial shows that you need to implement 'hook_field_formatter_info()'. When CCK invokes that hook, it's like CCK is asking "is there any module who wants to add a formatter?" If your module has implemented that hook, it will say "Yes, me!" and return the necessary information. That is how CCK will know about your formatter.

mxa055’s picture

You got me there :D exactly what I was thinking about knowing about the module existance. I am a programmer for a living but I haven't completely understood drupal's modularity just yet. Maybe a UML diagram would help :P

To my problem now...

I have made a module name nodereference_image inside the sites/all/modules directory containing two files .module and .info. I kinda understood whats involved except from this part:

function theme_nodereference_image_formatter($element) {
  $output = '';
  $nid = $element['#item']['nid'];
  if (!empty($nid) && is_numeric($nid) && ($title = _nodereference_titles($nid))) {
    $output = l($title, 'node/'. $nid, array('attributes' => array('target' => 'blank_')));
  }
  return $output;
}

where I don't know what this line should be replaced with:
$output = l($title, 'node/'. $nid, array('attributes' => array('target' => 'blank_')));
in order to get the imagefield CCK field to show up as a thumbnail (original size should be fine) and have a link pointing to the linkfield CCK field's link contained in the same node.

marcvangend’s picture

That's interesting... I build Drupal sites for a living and I think I understand 80% of Drupal's modularity. However I wouldn't call myself a programmer and I needed wikipedia to remind me what an UML diagram exactly is. Funny to see how we all have a slightly different angle.

In theme_nodereference_image_formatter(), the l() function returns html code for a link. You will have to replace that by something that returns the html code for your image. To do that, you will have to load the referenced node first, because the $element variable will not contain info about the image in the referenced node. Once you have retrieved the node, you can use the data to generate the html (for instance using theme_image()) and return it. That will probably look something like this:

<?php
function theme_nodereference_image_formatter($element) {
 
$output = '';
 
$nid = $element['#item']['nid'];
  if (!empty(
$nid) && is_numeric($nid)) {
   
$referenced_node = node_load($nid);
   
$imagepath = $referenced_node['field_image'][0]['filepath'];
   
$title = $referenced_node['title'];
   
$output = theme('image', $imagepath, $title);
  }
  return
$output;
}
?>

Note that loading a full node is the easiest, but not the most performant way to get the image data. If you need to format a large number of node references on each page and you feel that it's slowing down your site, you could consider writing some custom code or using functions from other modules (filefield?) to get only the file path, just like _nodereference_titles() does in the previous example.

To really understand all this, it helps to understand the theme system. Forgive me if I'm writing things you already know. The theme system (see http://drupal.org/theme-guide/6 for documentation and http://drupal.org/node/165706 specifically for module developers) is the part of Drupal that produces html output. Modules provide default output for every element that can be themed, but the default output can be overridden by a theme. Theme output is always generated by calling the theme() function with a theme hook and some data. The theme function routes the call to either the theme override or the default implementation. In the code above, theme('image', $imagepath, $title) will be routed to themename_image(imagepath, $title) (if it exists) or theme_image(imagepath, $title) (the default implementation).

mxa055’s picture

Sorry for not getting back sooner but I was lost with sth else the past few days.

I tried that to no avail :(

Now after some tweaking here and there I managed to lose the widget option for image that was created by the above procedure. I think I need to start clean and retry this.

Thanks a lot for the help. I will let you know if I finally managed to fix it.