Embedding a View within a node can be done in several ways (e.g., see ViewField module for a very flexible CCK approach, or Insert View module for a tag-based approach). But what I wanted was to embed the same view for every node of a specific type, where the view's filter is context dependent on the node being displayed - e.g., a context sensitive - embedded view - per node-type
Overview: basic concept
Nodes on your site have relationships you'd like to exploit to create sophisticated node displays. For example, say you have "secondary" nodes (say of type 'artwork') that have a reference (e.g., say a nodereference) to a "primary" node (say of type 'artist'). You'd like to display some field(s) from all of the former as a list, table, or grid at the bottom of the later (e.g. display a mini-gallery of artwork images associated with each artist).
To accomplish this, we will create a custom View that selects only secondary-type nodes with a reference to the primary node being displayed. Then we will do some custom theming to display this view at the bottom of every primary node. In this way, the primary node knows nothing about the secondary nodes - it simply displays a custom view that will automatically pull in and theme all of the related secondary nodes. That's pretty cool!
In this article, I'll provide a recipe for this specific example, but I think this basic approach can be adapted to a wide variety of situations.
- You are using a template theme, and are not averse to a little custom theming.
- You are using Views and CCK.
- For my example, you need ImageField and NodeReference CCK types.
For some background info. see:
- Inserting Views http://drupal.org/node/48816
- Embed View without insert_view module http://drupal.org/node/47417
- Context-sensitive embedded views http://drupal.org/node/124446
- Theming nodes by content type http://drupal.org/node/17565
- Set view per node-type, not per node http://drupal.org/node/169692
Step 1: Create your content types
In this example, will use two content types, named "artist" and "artwork". The "artist" node-type can just be a basic page-type node. The "artwork" node-type requires two CCK fields: an ImageField, to hold an image of the artwork, and a NodeReferece field, to provide a reference back to the artist.
There is lots of documentation on creating CCK fields. But, be sure that in the NodeReference Data Settings, you restrict "Content types that can be referenced" to "artist". Another really handy trick, is to further restrict which nodes can be referenced to only those owned by the current user (so users can only reference their own nodes). To do this, create a simple View, named "users-artists", that Filters Node:Type is "artist" and Node:Author is the "currently logged-in user". Now use your new "users-artists" view to set the "Nodes that can be referenced" in the NodeReference field. (I just love the way CCK and Views work together!)
Step 2: Create a View to "pull-in" secondary nodes
- Create a new view, called "mini-gallery".
- Layout a block view for the "artwork" nodes. I used a "Bonus:Grid" view-type, with 10 images max. to create a 2-row gallery.
- Add any static header or footer info. you want displayed with the mini-gallery.
- Select the fields to display in the "artwork" mini-gallery. I display the Imagefield Thumbnail and the Title as link (so the user can link back to the artwork node from the mini-gallery).
Tip: I am using Lightbox2 and ImageCache to create a very nice way to browse through the images directly within the mini-gallery view. So I use "Lightbox2: Thumbnail->original" option for the Imagefield - nice!
- Add an Argument Type : Node Reference as "Use Empty Text"
- Add "
$args = arg(1);" to the Argument Handling code (leave out the quotes).
That's the magic bit that will make the whole thing "context sensitive".
- Filter Published Nodes of Node Type : artwork.
- Sort by Last Modified Date so newer images show up first, if you like.
Step 3: Custom theme artist nodes to display the mini-gallery view
- Create the file node-artist.tpl.php file in you theme directory by copying node.tpl.php
- After the $content div, add the following:
<div class="mini-gallery"> <?php
print theme('view', 'mini_gallery', 10, false, 'block', NULL); ?>
See How To: Embed a View along with background links above.
And that's it.
Because the view is displayed "embedded" within a node, arg(1) contains the node being displayed. The Argument Handling code saves this into $args. This allows the NodeReference Argument to select only nodes with a reference to the one currently being displayed.
To be quite honest, I'm not 100% sure how this actually works - if someone with the Drupal / PHP knowledge could explain the mechanism at work here, it'd be greatly appreciated, as this appears to be a very powerful and widely applicable technique.