Aloha, using Views 2 and Organic Groups. I have a group node called "project" which has "milestone" nodes naming 1 or more projects as audience.

No problem getting a project home page listing milestones associated with it. But now I'd like a report that lists each project with its milestones indented:

project 1
milestone 1
milestone 2
milestone 3

project 2
milestone 4
milestone 5
milestone 6

project 3
milestone 1
milestone 5
...

I thought Views 2 with attachments could do this, and it works if I show only one project at a time (as in here: http://drupaleasy.com/blogs/ultimike/2009/07/using-views-relationships-a...). But how to do the above list? Any help appreciated, I've exhausted my online search skills.

Comments

thinkyhead’s picture

I'm trying to figure this out as well. So far all the examples I've seen only allow you to attach a second view to a single master view. It seems like you should be able to use the Relationship and Attachment concept to do this. For example, create a view of "Department" nodes, then create an Attachment view of "Person" nodes, with a filter of "Department" (where "Department" is a Node Reference field set up as a relationship).

I think the trouble comes because the Views UI only generates a single query for a given view, and for this reason I don't think it's capable of displaying subviews interspersed with items in a view. I've yet to see any example that even attempts this.

However, there's a pretty cool solution. You can use the views theming facilities to create a node template that applies specifically to your "Department" list view, then use this snippet of code within your template file:

print views_embed_view($view_name, $display_id , $arg1...);

$view_name should equal the name of your view as shown in url when you edit it. (e.g., admin/build/views/edit/my_people)

$display_id can be found by looking at the href attribute of that display's tab in the view editor. For example, when I hover my mouse over a tab, it shows the link in Safari's status line as "Go to #views-tab-page_1 on this page." Or if you look at the source of the page you'll see something like:

<a href="#views-tab-default" id="views-tab-title-default">Defaults</a>
<a href="#views-tab-page_1" id="views-tab-title-page_1">My Page</a>

In this case you could use "default" or "page_1" as the $display_id.

Finally, the views_embed_view function takes any number of arguments which it passes to the view. You'll certainly be using a Node Reference field to filter the People that you want to show up in your subview, so you should just pass $node->nid as $arg1. Then in your view display, specify one Argument that applies to your Node Reference field.

I've just started to mess around with this myself, so far I built the subview and tested it with a numeric argument and that part works as expected. Now to create the view item template and see how it goes. I'll post my results soon.

thinkyhead’s picture

Okay, well that wasn't so hard. I now have a working hierarchical views page for my file releases! You can see it in action at my downloads page.

My first step was to create a view sub-display to display a list of "File Release" nodes. I created a new Block display with a Row Style of "Node" and added an Argument and set it to correspond to the Node Reference field that refers to a "Product" node. I left the argument settings as they were and pressed Update. Finally I set up my Sorting and Filters as usual - to show published File Release nodes in descending order by Post Date. I saved the display and tested it with some known Product Node IDs, and it worked as it should.

Next I made a master view-display to output a list of "Product" nodes. I set it the Row Style to "Fields" and added just the Title field. Then I clicked the "Theme: Information" link to figure out what template I would need. My view is called "file_releases" so the template I needed to create was views-view-fields--file-releases--page-1.tpl.php. I clicked the "Row style output" link in the theming information to get the default template code and pasted it into the file.

At the bottom of the file I threw in some debugging code so I could see what was going on:

  ob_start();
  print_r($fields);
  print '<pre>'. htmlentities(ob_get_clean()) .'</pre>';

I scanned through the $fields array to see if I could find the 'nid' field, but I realized that of course it wasn't going to be there because I didn't add it to the Fields list!

At this point I could have just switched to a Row Style of Node, but since I don't need the whole thing I just added the Node ID field to the Fields list.

While configuring the Node ID field I turned on "Exclude from display," but of course that prevents the field from being sent to the template! Once I turned that back off I could now see "Nid: 60" on the page. Now all I had to do was add a test to exclude that field from display and add the call to views_embed_view() like so:

  print views_embed_view('file_releases', 'block_1' , $fields['nid']->raw);

When everything was put together the final result looked like this:

<?php
// $Id: views-view-fields.tpl.php,v 1.6 2008/09/24 22:48:21 merlinofchaos Exp $
/**
 * @file views-view-fields.tpl.php
 * Default simple view template to all the fields as a row.
 *
 * - $view: The view in use.
 * - $fields: an array of $field objects. Each one contains:
 *   - $field->content: The output of the field.
 *   - $field->raw: The raw data for the field, if it exists. This is NOT output safe.
 *   - $field->class: The safe class id to use.
 *   - $field->handler: The Views field handler object controlling this field. Do not use
 *     var_export to dump this object, as it can't handle the recursion.
 *   - $field->inline: Whether or not the field should be inline.
 *   - $field->inline_html: either div or span based on the above flag.
 *   - $field->separator: an optional separator that may appear before a field.
 * - $row: The raw result object from the query, with all data it fetched.
 *
 * @ingroup views_templates
 */
?>
<?php foreach ($fields as $id => $field): ?>
  <?php if ($id !== 'nid'): ?>
    <?php if (!empty($field->separator)): ?>
      <?php print $field->separator; ?>
    <?php endif; ?>

    <<?php print $field->inline_html;?> class="views-field-<?php print $field->class; ?>">
      <?php if ($field->label): ?>
        <label class="views-label-<?php print $field->class; ?>">
          <?php print $field->label; ?>:
        </label>
      <?php endif; ?>
        <?php
        // $field->element_type is either SPAN or DIV depending upon whether or not
        // the field is a 'block' element type or 'inline' element type.
        ?>
        <<?php print $field->element_type; ?> class="field-content"><?php print $field->content; ?></<?php print $field->element_type; ?>>
    </<?php print $field->inline_html;?>>
  <?php endif; ?>
<?php endforeach; ?>

<?php
  print views_embed_view('file_releases', 'block_1' , $fields['nid']->raw);
?>
a_lawry’s picture

I've been playing around with a similar thing. It took a lot of searching the net and reading docs. I don't have it in front of me right now but I think you can achieve what you want using the GROUP BY option in the views settings. This causes the view to output several times, once for each value of the field you get it to group by.

You can then use the template files to override the output of the view.

thinkyhead’s picture

Sorting it just the way I want is impossible without using some other possible tricks. The setup is as follows....

Fields I am getting in front of the Group By field:

- Product Node Reference ID (for grouping)
- Node Title (for benefit of the sub-items)
- Node ID (for aggregation)

"SQL Aggregation Group By Fields" settings:

- Group on: Product Node Reference
- Aggregate with: Node ID
- Sort by: Product Node Reference <--- ???

Then I set the display filter to select only File Release node types. (You might think I could select Products too and this module would do something like JOIN them, but that isn't its purpose.)

Finally, I have the view display sort by Post Date, descending, to get the File Releases in the right order.

The output gets all the correct items, and the File Releases are sorted correctly within the Product groups. However, the Products themselves are sorted by Node ID, which isn't what I'm after. There's no facility to use the Title of the selected Products as a sort criterion since they're not JOINed in the query. If I elect to sort by Title in the Group By form, it sorts on the File Release title, and that ends up negating the Sort By Date that's set for the view-display (since there's then only one sub-item to sort by date).

It's not a huge problem. I could perhaps figure out some way to take the full results of the query and sort it by title afterwards. It just isn't possible within this module to get that exact behavior.

It's a young module, so maybe they'll address this kind of problem in the future.

a_lawry’s picture

Hi,

Actually I was referring to the built in views group by support. It's in the "Basic settings" "style" settings when editing a view. That's what I used to make:

http://www.bookmebookme.co.uk/drupal/performers

That is a view with the group by setting set to the taxonomy term field. Is this similar to what you are trying to do?

Todd Young’s picture

Is there any way to "group by" two levels of hierarchy? I'm building a view of forum posts and I'd like to print "headers" with the container names that appear upstream from each node, without duplicates. I can get the forum name printing properly, or if I change the "group by" to the parent term, then I can get a conatiner name. Both appear without duplication. But I can't figure out how to show the forum name, and any/all containers above that. My only guess is that I'll have to do some sort of page, calling a view repeatedly with arguments, or I'll have to do some sort of "view of views" thing. But I'm so close, any ideas?

a_lawry’s picture

I've just done another view with sub-headings and two columns. This time I did it without the group by option. I sorted the view by the taxonomy term (sub-headings). Then in my template I used the $view->result variable to track when a new heading needs to be added. I think you could use this method to get multiple levels of headings as long as each level was available as a field in the view.

This is my template code at the moment.

<?php
// $Id: views-view-unformatted.tpl.php,v 1.6 2008/10/01 20:52:11 merlinofchaos Exp $
/**
 * @file views-view-unformatted.tpl.php
 * Default simple view template to display a list of rows.
 *
 * @ingroup views_templates
 */

$num_rows = count($view->result);
$halfway = ceil($num_rows/2);
$cur_term = -1;

?>
<?php if (!empty($title)): ?>
  <h2><?php print $title; ?></h2>
<?php endif; ?>
<div class="faq-left-col left-col">
<?php
foreach($view->result as $rowcount => $view_row):
  if ($view_row->term_data_tid != $cur_term)
  {
    $cur_term = $view_row->term_data_tid;
    if ($rowcount >= $halfway)
    {
      $halfway = 99999;
?>
</div>
<div class="faq-right-col right-col">
<?php
    }
?>
    <h5 class="faq blue-heading"><?php print $view_row->term_data_name; ?></h5>
<?php
  }
?>
  <div class="faq-item">
    <?php print $rows[$rowcount]; ?>
  </div>
<?php
endforeach;
?>
</div>
izmeez’s picture

subscribing