How do I dynamically set the active menu item?
Solution 1
For similar purpose, I used menu_set_item()
. You should leave the $path
argument NULL
and use the menu item for the internal path of 'galleries/lastgallery'
as $router_item
.
function custom_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) {
if ($op == 'view' && $node->nid == 31) {
$path = drupal_get_normal_path('galleries/lastgallery');
if($path && $menu_item = menu_get_item($path)) {
menu_set_item(NULL, $menu_item);
}
}
}
Solution 2
As tmsimont pointed out, using menu_set_item()
has side-effects...
A quick look at menu_set_item() and menu_get_item() shows us that they trigger hooks and database calls (). Not perfect.
If you're using Drupal 7.9+, there's a new function called menu_tree_set_path()
that will do the trick:
menu_tree_set_path('user-menu', 'shopping-cart');
The first argument is the menu name followed by the path you want to select.
NOTE: This does not apply the .active
class but applies .active-trail
instead so you'll have to update your CSS to accommodate both!
Solution 3
I know I'm a bit late in the game here and this already has an answer but I thought I'd post this in case it helps someone
With reference to the problem of menu_set_item(NULL, $menu_item) killing local tasks - it's not limited to this.
I found that when using the discuss module it didn't load the block. I think the issue is that by doing something like:
$path = drupal_get_normal_path('galleries/lastgallery');
$menu_item = menu_get_item($path);
menu_set_item(NULL, $menu_item);
You effectively tell drupal you're on a different page/item.
The solution that worked for me was this:
$menu_item = menu_get_item();
$menu_item['href'] = 'galleries/lastgallery';
menu_set_item(NULL, $menu_item);
This seems to just play with the href and leave rest alone so local tasks still work and so did disqus.
iflamberg
Updated on June 16, 2022Comments
-
iflamberg almost 2 years
For example, I have "node/31". And I want drupal to set menu active item to "galleries/lastgallery" if node/31 is viewed. How to do it?
<?php function custom_nodeapi (&$node, $op, $a3 = NULL, $a4 = NULL){ if ($op == 'view' && $node->nid == 31) { ??? } } ?>
Updated: I know I can use
menu_set_active_item
. But in this case tabs (View/Edit etc. tabs) will be not displayed. I believe it should be done withmenu_set_active_trails
, or may bemenu_get_item
/menu_set_item
somehow, but I can't figure how exactly. -
gagarine over 11 yearsmenu_tree_set_path() is a better option.
-
Nadeem Ahmed over 11 yearsIndeed but menu_tree_set_path() has been introduced in Drupal 7, the question is for Drupal 6.
-
gagarine over 11 yearsThis do not work for the front page... I try to use <front> as a path without success.
-
jmlnik over 11 yearsTo use aliases, you could potentially wrap the path in
drupal_get_normal_path()
, eg:menu_tree_set_path('my-menu', drupal_get_normal_path('<front>'))
. Let me know if it works and I'll update the answer.