Yii how to highlight the current menu item

2019-07-17 12:09发布

问题:

I used the following code to display the menu items.

Here by default the 'Home' link should be activated. So that i used the code

active' => $this->id =='default' ? true : false

$this->widget('zii.widgets.CMenu',array(
     'linkLabelWrapper' => 'span',
    'items'=>array(
    array('label'=>'Home', 'url'=>array('post/index'),'active'=>$this->id=='default'?true:false),
    array('label'=>'About', 'url'=>array('site/page', 'view'=>'about'),'active'=>$this->id=='about'?true:false),
    array('label'=>'Test', 'url'=>array('site/page', 'view'=>'test')),
    array('label'=>'Contact', 'url'=>array('site/contact')),
    array('label'=>'Login', 'url'=>array('site/login'), 'visible'=>Yii::app()->user->isGuest),
    array('label'=>'Logout ('.Yii::app()->user->name.')', 'url'=>array('site/logout'), 'visible'=>!Yii::app()->user->isGuest)
    ),
    )); 

I referred the url http://www.yiiframework.com/doc/api/1.1/CMenu#activateItems-detail But i dont know how to use these parameters. Please help

回答1:

Not the Yii way, but the (simpler) jQuery way:

// find menu-item associated with this page and make current:
$('a').each(function(index, value) { 
    if ($(this).prop("href") === window.location.href) {
        $(this).addClass("current-page");
    } 
});


回答2:

The code you give will be typically found inside a view. The documentation for view states that

Inside the view script, we can access the controller instance using $this. We can thus pull in any property of the controller by evaluating $this->propertyName in the view.

So, we have established that in the current context, $this->id refers to the CController::id property. This id will typically be the prefix of your controller's class name. For example, inside MyController you will have $this->id == "my".

With all this in mind, you can now tell that active will be true if and only if the current view is rendered from inside a controller named DefaultController. However, from the url property of that menu item we see that the associated controller for that action (assuming default routing) is PostController. So the $this->id == "default" idea is faulty.

If you want to make the "Home" item active whenever any action in your PostController is running, you should change this to $this->id == "post". Normally it should not be necessary to do this, because the activateItems property (which defaults to true) used with default routing will take into account both the controller id and the current action to determine which menu item to make active.



回答3:

if you have some advanced link structure, put method below in Controller

/**
 * Checks if the current route matches with given routes
 * @param array $routes
 * @return bool
 */
public function isActive($routes = array())
{
    $routeCurrent = '';
    if ($this->module !== null) {
        $routeCurrent .= sprintf('%s/', $this->module->id);
    }
    $routeCurrent .= sprintf('%s/%s', $this->id, $this->action->id);
    foreach ($routes as $route) {
        $pattern = sprintf('~%s~', preg_quote($route));
        if (preg_match($pattern, $routeCurrent)) {
            return true;
        }
    }
    return false;
}

//usage
'items'=>array(
    array('label'=>'Some Label', 'url'=>array('some/route'),'active'=>$this->isActive(array(
        'some/route',
        'another/route',        
    )),    
),


回答4:

I used this way:

array('label'=>'Contact', 'url'=>array('site/contact'), 'active'=>strpos(Yii::app()->request->requestUri, Yii::app()->createUrl('site/contact'))===0)


回答5:

The menu will work as we use default pages as site/contact, site/login But many times it will not work for the module url.

suppose i have module user and i had login action in login controller, so i can do below thing form menu as how menu item gets active defined below.

array('label'=>Yii::t('frontend','Login'), 'url'=>array('/user/login/login'), 'visible'=>Yii::app()->user->isGuest), // Working, Login tag activated on login page

array('label'=>Yii::t('frontend','Login'), 'url'=>array('/user/login'), 'visible'=>Yii::app()->user->isGuest), // Not working, Login tag not activated on login page

So, we can have problem to beautify url..



回答6:

For yiistarterkit just add this code in the _base.php file:

function isActive($routes = array())
{
    if (Yii::$app->requestedRoute == "" && count($routes) == 0){
        return true;
    }
    $routeCurrent = Yii::$app->requestedRoute;
    foreach ($routes as $route) {
        $pattern = sprintf('~%s~', preg_quote($route));
        if (preg_match($pattern, $routeCurrent)) {
            return true;
        }
    }
    return false;
}

And then use:

echo Nav::widget([
'options' => ['class' => 'navbar-nav navbar-left'],
'items' => [
    ['label' => \Yii::t('frontend', 'Home'), 'url' => ['/'], 'active'=>isActive()],
    ['label' => \Yii::t('frontend', 'Services'), 'url' => ['/services'], 'active'=>isActive(['services'])],
]
]);


回答7:

Take as a base the file yiisoft/yii2-boostrap/nav.php function renderItem():

...
if ($this->activateItems && $active) {
    Html::addCssClass($options, 'active');
}       
return Html::tag('li', Html::a($label, $url, $linkOptions) . $items, $options);

And modify $option on $linkOption for a link.

Html::addCssClass($linkOptions, 'active');

As result active class will be added to a.class, instead li.class