Yii Framework Forum: override CMenu isItemActive() to activate menu according to GET parameter - Yii Framework Forum

Jump to content

Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

override CMenu isItemActive() to activate menu according to GET parameter needs revision Rate Topic: -----

#1 User is offline   bettor 

  • Master Member
  • PipPipPipPip
  • Yii
  • Group: Members
  • Posts: 752
  • Joined: 02-February 09

Posted 19 January 2010 - 12:07 PM

hi all,

I ran into a situation in which I am using CMenu [very nice widget] for my main menu. However, three of my menu options use the same controller/action and only different id parameter. So when I clicked one of the three menu options as a result all three were marked as active. So I decided to extend the CMenu class and customize it in a way that Yii decides which option is active according to the 'id' attribute. If you know a better solution please share.

I created a new file in components and named it CCustomMenu.php

In the layouts/main.php file make sure that the label of the menu is identical to the id attribute:
<?php $this->widget('CCustomMenu',array(
			'items'=>array(
				array('label'=>'Home', 'url'=>array('/site/index','id'=>'Home')),
                                array('label'=>'Services', 'url'=>array('/site/index','id'=>'Services')),
                                array('label'=>'Projects', 'url'=>array('/site/index','id'=>'Projects')),
				array('label'=>'About us', 'url'=>array('/site/page', 'view'=>'about')),
				array('label'=>'Contacts', 'url'=>array('/site/contact')),
				array('label'=>'Login', 'url'=>array('/site/login'), 'visible'=>Yii::app()->user->isGuest),
				array('label'=>'Изход ('.Yii::app()->user->name.')', 'url'=>array('/site/logout'), 'visible'=>!Yii::app()->user->isGuest)
			),
		)); ?>


in my CCustomMenu.php I override the isItemActive() function to change the logic a bit:

protected function isItemActive($item,$route)
	{

                 if(isset($item['url']) && isset($item['label']) && is_array($item['url']) && isset($item['id']) && strtolower($item['label'])===strtolower($item['id']))
                    {
                     if(count($item['url'])>1)
			{
				foreach(array_splice($item['url'],1) as $name=>$value)
				{
					if(!isset($_GET[$name]) || $_GET[$name]!=$value)
						return false;
				}
			}
			return true;
                 }elseif(isset($item['url']) && is_array($item['url']) && !strcasecmp(trim($item['url'][0],'/'),$route))
                         {
                     if(count($item['url'])>1)
			{
				foreach(array_splice($item['url'],1) as $name=>$value)
				{
					if(!isset($_GET[$name]) || $_GET[$name]!=$value)
						return false;
				}
			}
			return true;
		}
		return false;
                 }


Basically, I included one more if logic to check if label===id and switch to active. If anybody has a better idea please share with me. If not I hope this can be usefull for other people too.

cheers,
b
0

#2 User is offline   qiang 

  • Yii Project Lead
  • Yii
  • Group: Yii Dev Team
  • Posts: 5,900
  • Joined: 04-October 08
  • Location:DC, USA

Posted 19 January 2010 - 12:09 PM

Thanks for sharing. You also also directly configure the 'active' property of the menu items to cope with complex conditions.
0

#3 User is offline   jacmoe 

  • Elite Member
  • Yii
  • Group: Moderators
  • Posts: 2,601
  • Joined: 10-October 10
  • Location:Denmark

Posted 31 October 2010 - 02:01 PM

Thanks for the tip! :)

This is my overridden isItemActive function:
	protected function isItemActive($item, $route) {
    	if (isset($item['id'])) {
        	if($route === $item['id'])
            	return true;
        	return false;
    	}
    	return false;
	}

It requires that the 'id' attribute of the menu entries are set to the route.
For example:
                	'items' => array(
                    	array('label' => 'Home', 'url' => array('/site/index'), 'id' => 'site/index'),
                    	array('label' => 'Projects', 'url' => array('/projects/'), 'id' => 'project/index'),
                    	array('label' => 'Overview', 'url' => array('/projects/' . $_GET['name']), 'id' => 'project/view'),
                    	array('label' => 'Activity', 'url' => array('/projects/' . $_GET['name'] . '/activity'), 'id' => 'project/activity'),
                    	array('label' => 'Roadmap', 'url' => array('/projects/' . $_GET['name'] . '/roadmap'), 'id' => 'project/roadmap'),
                	),


I have custom URL rules, btw. Hence the use of $_GET['name'] ..
"Less noise - more signal"
0

Share this topic:


Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

1 User(s) are reading this topic
0 members, 1 guests, 0 anonymous users