17

Say you have the following pages in a menu tree:

  • Projects
    • Project One
    • Project Two
    • Project Three

I'm looking for a way to create a view that will be embedded in the Project (parent) page that will show a pic, title and text (summary) from the child pages.

The relationship between the parent and the children is defined in the menu tree.

I know I can use node reference, but that would mean every time someone creates a page they would have to define the menu relationship and then the node reference relationship.

Also I know that I could create another content-type but I think this is overkill as all content pages look the same.

1
  • 1
    There is no direct relation between nodes which are displayed in a submenu of another node (The only connection between a menu link and a node is that a menu link points to node/nid). So you need something to link these sub-nodes together (and to the parent-node), could be a common taxonomy term, book.module, ...
    – Berdir
    Commented Apr 13, 2011 at 12:20

9 Answers 9

4

One solution is to use taxonomy terms to define the relationships and then to use the Taxonomy Menu module to translate those term relationships into menu items. You can then use the Custom Page module and Context modules to control information and regions on all the pages if you don't want to use panels.

16

You can do exactly this using the Menu Node API and the Menu Node Views modules.

Create a view with your required content type, and choose a contextual filter of "Menu: Menu link ID" (this is only available with the above modules installed).

Under, "When the filter value is not available," select "Provide default value" and choose "PHP code."

The following snippet will do it, then you just expose a block from the view and you are there:

if (function_exists('menu_node_get_links')){  
   $node = node_load(intval(arg(1)));  
   if (isset($node->menu_node_links)){
      foreach($node->menu_node_links as $mlid=>$data){  
         return $mlid;
      }  
   }
}
4
  • 3
    I think the filter should be "Menu: Parent menu link id" in order to take the children of the current node. And the argument code can be: $current = end(menu_get_active_trail()); return $current['mlid'];
    – Stefan
    Commented Nov 23, 2011 at 12:17
  • Thanks for this. A few improvements (in addition to @Stefan's correction). 1) You can use menu_load_object(arg(1)) instead of node_load() to save some expense. 2) You should check to make sure that the menu item is from the menu you're concerned with. Right now, you're just returning the first $mlid. Inside the foreach you should add a conditional if ($data->menu_name == 'my-menu') to fix this. and 3) You might want to add a second filter for menu: hidden to only return items that aren't hidden. Use the same snippet, but return the $data->hidden; instead of the $mlid. Commented Dec 11, 2013 at 20:09
  • 2
    I would strongly discourage suggesting modules which are still in development stage.
    – Ambidex
    Commented Mar 26, 2014 at 13:47
  • @Stefan is there away to get all children at any level? instead of just first.
    – Eli Stone
    Commented Jan 7, 2016 at 13:30
4

The Node Hierarchy Module allows this type of relationship, as well as providing a views integration.

Node Hierarchy allows nodes to be children of other nodes creating a tree-like hierarchy of content. The module offers:

  • 1-Click creation of hierarchical menus

  • Hierarchical breadcrumbs

  • Automatic hierarchical urls using Pathauto (and token module)

    (eg: q=aboutus/history/beginning).

  • Automatic creation of hierarchical menus if desired.

  • Optional Views integration.

  • Optional Node Access integration.

2

Maybe this has changed for D7/Views 3, but you don't need any PHP in order to accomplish the desired behavior:

  1. install menu_views, menu_node and menu_node_views modules.
  2. create a new view of type "menu tree"
  3. add fields "Menu: link title" and "Menu: description"
  4. Add Contextual Filter/Argument "Menu: Node ID"; Provide default value "Content ID from URL"
  5. Add Relationship "Menu: Parent menu link id"

voila. It shouldn't work, but it does.

It works fine with just nodes, but the advantage of using menu links over node hierarchy is that you're not limited to building navigation around nodes. You could even include external links in your view.

2
  • This is a good option for exposing node links (and I love that Aaron Bauman put up this sample view to import: pastebin.com/u2GjmWG7). However, I had some trouble making node fields available to the view, as the OP was requesting. How is that accomplished?
    – doub1ejack
    Commented Jul 31, 2013 at 19:28
  • You should be able to expose node fields by adding a relationship to "Menu: Node ID." Do you see something like that? Commented Aug 14, 2013 at 17:29
2

There's a relatively new module Views Menu Node Children Filter that seems to do exactly what you want:

This module adds a contextual filter to Views that will retrieve a node's child nodes according to a menu's structure.

0

Have you considered using Node Reference for this purpose?

  1. Provide a node reference field to the content type you want to display.
  2. Use that field as a contextual filter in the View (default value: Content ID from url).
  3. Add this view display as a block to the content. The node in which it's being displayed will be seen as a parent of the nodes that reference to it for instance.

Thus you can achieve a similar outcome as you're probably looking for.

0

The answer from Emile is right, but I had to paste the mentionned PHP code in a contextual filter of the type " Menu: Parent menu link id ".

if (function_exists('menu_node_get_links')){  
   $node = node_load(intval(arg(1)));  
   if (isset($node->menu_node_links)){
      foreach($node->menu_node_links as $mlid=>$data){  
         return $mlid;
      }  
   }
}
0

If you use entity translation and the node is attached to different menus, here is an adaptation of the code that filters on the current language. You need to copy this as PHP code for the contextual filter (parent menu link id) in your view like explained in the other answers

 if (function_exists('menu_node_get_links')) {
global $language;
$lang = $language->language;
$node = node_load(intval(arg(1)));
if (isset($node->menu_node_links)) {
  foreach ($node->menu_node_links as $mlid => $data) {  
    if ($lang == $data->language) {
      return($mlid);
    }
  }
}
  }
0

From the issue queue of Menu Node Views we have this nice solution :

  • add a contextual filter with 'Parent menu link id',
  • select 'Provide default value'
  • select 'custom php code'
  • enter the following code

    $menu_item = menu_get_active_trail();  
    $current_item = array_pop($menu_item);  
    $menu_item_plid = $current_item['plid'];  
    return $menu_item_plid;  
    

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.