Posted by rooey on January 19, 2007 at 9:43am
What's the rule-of-thumb in getting subtabs to display as subtabs?
I have 4 "tabs" - and want 2 sub-tabs for each:
( category 1 ) ( category 2 ) ( category 3 ) ( category 4 )
( view ) ( edit )
I can get the 4 categories to display correctly, but can't get the subtabs up at all.
Can someone explain how this is supposed to work, or point me in the direction of something that does?
Thanks in advance.
Roo.
Comments
Here's the menu structure
//main tabs
$items[] = array('path' => 'ermm/profitability/jobs', 'title' => t('Jobs'),
'callback' => 'ermmprofitability_list',
'callback arguments' => array('job codes'),
'access' => user_access('access ermmprofitability'),
'type' => MENU_DEFAULT_LOCAL_TASK
);
$items[] = array('path' => 'ermm/profitability/businessunits', 'title' => t('Business units'),
'callback' => 'ermmprofitability_list',
'callback arguments' => array('business units'),
'access' => user_access('access ermmprofitability'),
'type' => MENU_LOCAL_TASK,
'weight' => 2
);
$items[] = array('path' => 'ermm/profitability/customers', 'title' => t('Customers'),
'callback' => 'ermmprofitability_list',
'callback arguments' => array('customers'),
'access' => user_access('access ermmprofitability'),
'type' => MENU_LOCAL_TASK,
'weight' => 2
);
$items[] = array('path' => 'ermm/profitability/groups', 'title' => t('Groups'),
'callback' => 'ermmprofitability_list',
'callback arguments' => array('groups'),
'access' => user_access('access ermmprofitability'),
'type' => MENU_LOCAL_TASK,
'weight' => 2
);
//sub-tabs for viewing/editing
if (arg(2) == 'jobs' && is_numeric(arg(3))) {
$items[] = array(
'path' => 'ermm/profitability/'.arg(2).'/'.arg(3),
'title' => t('View'),
'callback' => 'ermmprofitability_view',
'callback arguments' => array(arg(2)),
'access' => ('access ermmprofitability'),
'type' => MENU_CALLBACK,
'weight' => -10);
$items[] = array(
'path' => 'ermm/profitability/'.arg(2).'/'.arg(3).'/view',
'title' => t('View'),
'type' => MENU_DEFAULT_LOCAL_TASK,
'weight' => -10);
$items[] = array(
'path' => 'ermm/profitability/'.arg(2).'/'.arg(3).'/edit',
'title' => t('Edit'),
'callback' => 'ermmprofitability_edit',
'callback arguments' => array(arg(2)),
'access' => ('administer ermmprofitability'),
'weight' => -1,
'type' => MENU_LOCAL_TASK);
$items[] = array('path' => 'ermm/profitability/'. arg(2).'/'.arg(3) .'/delete',
'title' => t('Delete'),
'callback' => 'drupal_get_form',
'callback arguments' => array('ermm_delete_confirm', arg(3)),
'access' => ('administer ermmprofitability'),
'type' => MENU_CALLBACK);
}
I have just been playing
I have just been playing with this myself. This is what I know.
1) you have to have a base MENU_CALLBACK, and then one tab must be MENU_DEFAULT_LOCAL_TASK (which inherits settings from the base)
2) the 'path' defines the groups/children.
so in your example you have main paths:
ermm/profitability/jobs
ermm/profitability/businessunits
etc,
Then children:
ermm/profitability/jobs/x <-- parent, x is a number
ermm/profitability/jobs/x/view <-- MENU_DEFAULT_LOCAL_TASK
Which looks right to me. I'm not sure why it doesnt work. I see you:
if (arg(2) == 'jobs' && is_numeric(arg(3))) {
are you sure its going inside the if? why dont you drop a 'die' statement in there and just make sure it's getting hit.
Mine look like this:
<?php
// main items
$items[] = array(
'access' => $access,
'callback' => 'vcsshop_admin',
'path' => 'admin/content/vcsshop',
'title' => 'VCS Shopping',
);
$items[] = array(
'access' => $access,
'path' => 'admin/content/vcsshop/list',
'type' => MENU_DEFAULT_LOCAL_TASK,
'title' => 'List',
'weight' => -10
);
$items[] = array(
'access' => $access,
'callback' => 'drupal_get_form',
'callback arguments' => array('vcsshop_edit'),
'path' => 'admin/content/vcsshop/add',
'title' => 'Add New',
'type' => MENU_LOCAL_TASK,
);
// ---- then the groups
$items[] = array(
'access' => $access,
'callback' => 'vcsshop_groups',
'path' => 'admin/content/vcsshop/groups',
'title' => 'Order Groups',
'type' => MENU_LOCAL_TASK,
);
$items[] = array(
'access' => $access,
'path' => 'admin/content/vcsshop/groups/list',
'title' => 'List',
'type' => MENU_DEFAULT_LOCAL_TASK,
'weight' => -10
);
$items[] = array(
'access' => $access,
'callback' => 'drupal_get_form',
'callback arguments' => array('vcsshop_groups_edit'),
'path' => 'admin/content/vcsshop/groups/add',
'title' => 'Add Group',
'type' => MENU_LOCAL_TASK,
);
$items[] = array(
'access' => $access,
'callback' => 'drupal_get_form',
'callback arguments' => array('vcsshop_groups_edit'),
'path' => 'admin/content/vcsshop/groups/edit',
'title' => 'Edit Group',
'type' => MENU_CALLBACK,
);
$items[] = array(
'access' => $access,
'callback' => 'drupal_get_form',
'callback arguments' => array('vcsshop_groups_delete'),
'path' => 'admin/content/vcsshop/groups/delete',
'title' => 'Delete Group',
'type' => MENU_CALLBACK,
);
?>
Sorry, I dont think I'm much help
-Andy
debug
yep, it's going inside the if for sure - but no child tabs - they overwrite the base ones.
Ok, this has got me totally
Ok, this has got me totally boggled.
msg_r($items) shows me that the menu items are being built correctly - they simply aren't displaying as I would expect.
Anyone?
Example of setting up tabbed menu with MENU_DEFAULT_LOCAL_TASK
In case anyone else ends up here, these are the rules of thumb I've evolved for making tabbed menus in Drupal 5.1:
First, make sure all your URLs nest nicely:
submenu/animals
submenu/animals/cats
submenu/animals/dogs
submenu/vegetables
submenu/vegetables/artichokes
submenu/vegetables/tomatoes
Above, you want to end up with two tabsets, one for animals (one tab for cats, one for dogs), one for vegetables (tomatos, artichokes), off the main menu item, which is submenu.
So you have a tree of paths, and the idea is to decorate each node of each path with a form-building function, and also to mark a branch (path) through the tree, such that a leaf of the tree is displayed to the user when the user first clicks on the submenu link -- i.e., a default path. [Not Drupal nodes, but generic nodes, as in "nodes and arcs."]
The "decorate with functionality" part is done with callbacks, and the "mark a branch" part is done by marking each node's #type with the constants MENU_LOCAL_TASK or MENU_DEFAULT_LOCAL_TASK. The DEFAULT_LOCAL_TASKS mark the default path to a leaf.
My rule of thumb is to put the callback as HIGH in the tree as possible, and mark as default ALL THE WAY DOWN the tree to a leaf. This is confusing, because there won't be a function at the leaf, but Drupal will climb up the tree from the leaf, higher, until it finds one.
Here is a worked example, with stuff like titles and descriptions and weights and access left out:
// Root to the submenu; needs no type
$items[] = array(
'path' => 'submenu',
);
// callback function for "cats" high up in the tree
$items[] = array(
'path' => 'submenu/animals',
'type' => MENU_LOCAL_TASK,
'callback' => 'drupal_get_form',
'callback arguments' => array('get_the_cats'),
);
// marked as default down at a leaf (this tab will end up underlined)
$items[] = array(
'path' => 'submenu/animals/cats',
'type' => MENU_DEFAULT_LOCAL_TASK,
);
$items[] = array(
'path' => 'submenu/animals/dogs',
'callback' => 'drupal_get_form',
'callback arguments' => array('get_the_dogs'),
'type' => MENU_LOCAL_TASK,
);
$items[] = array(
'path' => 'submenu/vegetables',
'type' => MENU_LOCAL_TASK,
'callback' => 'drupal_get_form',
'callback arguments' => array('get_the_artichokes'),
);
// when the Vegetables tab is clicked on, this will be the default, and get_the_artichokes will be the callback
$items[] = array(
'path' => 'submenu/vegetables/artichokes',
'type' => MENU_DEFAULT_LOCAL_TASK,
);
$items[] = array(
'path' => 'submenu/vegetables/tomatos',
'callback' => 'drupal_get_form',
'callback arguments' => array('get_the_tomatoes'),
'type' => MENU_LOCAL_TASK,
);
I hope this helps somebody -- I'm sure there are nuances that I've missed, like how the tabs get ordered, and YMMV, so comments welcome.
http://www.universalpantograph.com
http://www.universalpantograph.com
how about to std node tabs
going through post above and i can't get this to work for my example; but perhaps different enough that it doesn't wotk in this case (although i don't think it should be).
I am trying to add a new tab (authenticate) on a std node view to go alongside the existing tabs: view, edit, etc.. and then to that new tab add various sub tabs (yahoo in example code).
from above i think i should need this:
$items[] = array('path' => 'node/'. arg(1) .'/auth',
'title' => t('Authenticate'),
'callback' => '_auth_landing',
'access' => user_access('authenticate documents'),
'weight' => 7,
'type' => MENU_LOCAL_TASK,
);
$items[] = array(
'path' => 'node/'. arg(1) .'/auth/yahoo',
'title' => t('Yahoo'),
'callback' => '_auth_confirm_page',
'access' => user_access('authenticate documents'),
'weight' => 7,
'type' => MENU_LOCAL_TASK,
);
All i get is the Authenticate top level tab - can't get Yahoo as sub-tab off that.
Peter Lindstrom
LiquidCMS - Content Management Solution Experts
Peter Lindstrom
LiquidCMS - Content Solution Experts
i gave up
I was never able to figure it out.
Its working !
i don't know why its not working for you ! its working for me, i will show my code.
<?php
function oa_reports_menu(){
if(arg(0)=="node" && is_numeric(arg(1))){
// check if node is a project
$node=node_load(arg(1));
if($node->type=="project"){
$items=array();
$items[] = array(
'path' => 'node/'.arg(1).'/all_reports',
'title' => t('Reports'),
'callback'=>'oa_reports_list',
'type' => MENU_LOCAL_TASK,
'access'=>true,
'weight'=>2,
);
$items[] = array(
'path' => 'node/'.arg(1).'/all_reports/trial_balance_report',
'title' => t('Trial Balance'),
'callback'=>'oa_reports_trial_balance',
'type' => MENU_DEFAULT_LOCAL_TASK,
'access'=>true,
'weight'=>2,
);
$items[] = array(
'path' => 'node/'.arg(1).'/all_reports/balance_sheet_report',
'title' => t('Balance Sheet'),
'callback'=>'oa_balance_sheet_report',
'type' => MENU_LOCAL_TASK,
'access'=>true,
'weight'=>2,
);
return $items;
}
}
}
function oa_reports_list(){
return "Reports";
}
function oa_reports_trial_balance(){
return "Trial Balance";
}
function oa_balance_sheet_report(){
return "Balance Sheet";
}
?>
subscribing
subscribing