I’ve seen a few posts questions over the last few years asking how to build a dynamic submenu.
I came across an article on your blog here on how to use CPortlets to build a user menu, which is great but it’s using static html.
So I tried to use this logic to build a widget that was dynamic, such that you can define the sub-menu items in the controller.
The problem being though, that the submenu wouldn’t be part of the content and would therefore need to be rendered by the layout.
I’ve tried creating a submenu Portlet widget and then using a callback function, to the controller to get the menu items.
When I trace through it looks like it is working but the menu is not being rendered.
I’m wondering whether the layout has already been rendered by the time the controller callback has been called.
Any ideas?
Here is the code:
components/submenu.php
Yii::import('zii.widgets.CPortlet');
class SubMenu extends CPortlet
{
public $title;
public $menu;
public function init()
{
$this->hideOnEmpty=true;
$controllerId = Yii::app()->controller;
fb($controllerId);
if (method_exists($controllerId, 'getSubMenu')) {
$menu= $controllerId->getSubMenu();
}
parent::init();
}
protected function renderContent()
{
if (isset ($menu)) {
$this->render('subMenu', array('menu'=>$menu));
}
}
}
components/views/submenu.php
<ul>
<?php
foreach ($menu as $menuName=>$menuLink) {
echo "<li>".CHtml::link($menuName,array($menuLink))."</li>";
}
?>
</ul>
controller/some_controller.php
public function getSubMenu() {
$subMenuItems=array();
if(UserModule::isAdmin()) {
$mu=UserModule::t('Manage User');
$subMenuItems[$mu]='/user/admin';
$subMenuItems[UserModule::t('List User')]='/user';
}
$subMenuItems[UserModule::t('Profile')]='/user/profile';
$subMenuItems[UserModule::t('Edit')]='edit';
$subMenuItems[UserModule::t('Change password')]='changepassword';
$subMenuItems[UserModule::t('Logout')]='/user/logout';
fb($subMenuItems);
return $subMenuItems;
}
layout/main.php
<div id="submenu">
<?php $this->widget('SubMenu'); ?>
</div>