ItemClass from parent menu cascades into submenu wrapper
bluec opened this issue · comments
Not easy to explain but it seems the addItemClass()
from a menu gets applied to the container of the submenu.
An example is worth a thousand words... example Bootstrap 4 styled menu and submenu:
Menu::new()
->addClass('nav')
->addItemParentClass('nav-item')
->addItemClass('nav-link')
->link('#', 'Main Menu Link 1')
->link('#', 'Main Menu Link 2')
->submenu(
Link::to('#', 'Sub Menu')
->addClass('nav-link nav-dropdown-toggle')
,
Menu::new()
->addClass('nav-dropdown-items') // this has nav-link class from parent menu but it shouldn't
->addParentClass('nav-dropdown')
->addItemParentClass('nav-item')
->addItemClass('nav-link')
->link('#', 'Sub Menu Item 1')
->link('#', 'Sub Menu Item 2')
);
This HTML is generated:
<ul class="nav">
<li class="nav-item"><a href="#" class="nav-link">Main Menu Link 1</a></li>
<li class="nav-item"><a href="#" class="nav-link">Main Menu Link 2</a></li>
<li class="nav-dropdown nav-item"><a href="#" class="nav-link nav-dropdown-toggle">Sub Menu</a>
<ul class="nav-dropdown-items nav-link">
<li class="nav-item"><a href="#" class="nav-link">Sub Menu Item 1</a></li>
<li class="nav-item"><a href="#" class="nav-link">Sub Menu Item 2</a></li>
</ul>
</li>
</ul>
This is what should be generated:
<ul class="nav">
<li class="nav-item"><a href="#" class="nav-link">Main Menu Link 1</a></li>
<li class="nav-item"><a href="#" class="nav-link">Main Menu Link 2</a></li>
<li class="nav-dropdown nav-item"><a href="#" class="nav-link nav-dropdown-toggle">Sub Menu</a>
<ul class="nav-dropdown-items">
<li class="nav-item"><a href="#" class="nav-link">Sub Menu Item 1</a></li>
<li class="nav-item"><a href="#" class="nav-link">Sub Menu Item 2</a></li>
</ul>
</li>
</ul>
I had the exact same issue as @bluec so I submitted a pull request to fix what I could see as being the problem and wrote a test to capture the use case above.
If for any reason @sebastiandedeyne decides not to merge in that pull request, I found a way around this by creating a class that inherits from the \Spatie\Menu\Menu
:
<?php
namespace App\Http\Menus\Menu;
class MenuExtended extends \Spatie\Menu\Menu
{
/**
* Add a class to all items in the menu.
*
* @param string $class
*
* @return $this
*/
public function addItemClass(string $class)
{
$this->applyToAll(function (\Spatie\Menu\Link $link) use ($class) {
$link->addClass($class);
});
return $this;
}
}
Or, if you are using the Laravel Menu package \Spatie\Menu\Laravel\Menu
:
<?php
namespace App\Http\Menus\Menu;
class MenuExtended extends \Spatie\Menu\Laravel\Menu
{
/**
* Add a class to all items in the menu.
*
* @param string $class
*
* @return $this
*/
public function addItemClass(string $class)
{
$this->applyToAll(function (\Spatie\Menu\Link $link) use ($class) {
$link->addClass($class);
});
return $this;
}
}
Since the Menu::new()
, Menu::build()
and Menu::blueprint()
methods use late static binding, subsequent calls to build menus will use the overriding class above instead of the package classes.
Gonna close this, being handled in #88.
I am having the exact same issues. Sad to see, that the correcting PRs never got merged :(