laravel-menu icon indicating copy to clipboard operation
laravel-menu copied to clipboard

Specify menu depth

Open Roywcm opened this issue 10 years ago • 14 comments

Is it possible to specify a menu depth? Like Menu::get('mainnav')->maxdepth(1) for showing only the top navigation.

Roywcm avatar Oct 08 '14 11:10 Roywcm

Please update the package. If you need to target items at root level you can do like so

<?php
Menu::get('mainnav')->roots();

// or alternatively call whereParent with no argument.

Menu::get('mainnav')->whereParent();

You can also call children() if you just need to fetch the children of an item and not all the descendants.

for example to add data-role attribute to children of item `About, you can do like so:

<?php
Menu::get('mainnav')->item('about')
                    ->children()
                    ->attr('data-role', 'navigation');

And if you need to affect all descendants:

<?php
Menu::get('mainnav')->item('about')
                    ->all()
                    ->attr('data-role', 'navigation');

lavary avatar Oct 10 '14 23:10 lavary

Thank you, but for some reason i'm getting this error when I do this:

Menu::get('navigation')->roots()->asUl(array('class'=>'nav navbar-nav'))

Call to undefined method Lavary\Menu\Collection::asUl()

Roywcm avatar Oct 13 '14 19:10 Roywcm

Currently you can't call rendering methods on collections. roots() returns a Laravel collection. You may use CSS to style your menu the way you need or create a custom rendering method. It is explained in the Advanced Usage section.

However it's a good idea to have rendering methods on collections too. I'll add this feature to the package soon.

Stay tuned!

lavary avatar Oct 15 '14 22:10 lavary

@lavary maybe it's possible you could add a method to the Item class that would get return the current depth of the iteration. The reason for this is for sub-menu items and the layout.

I've extended your Item class in my project to add this functionality. The reason was that the theme I am using uses css class names for it's depth.

<ul class="nav nav-{{$item->depth()}}-level"
    @include('backend.menu-items', array('items' => $item->children()))
</ul>

In my case the depth returned "first", "second", or "third" .. but that would be simple to translate from an Integer.

Just an idea!

MattWohler avatar Nov 20 '14 23:11 MattWohler

@MattWohler Sounds like a good idea Matt. I think I'm gonna need to add this to the package :)

lavary avatar Nov 21 '14 22:11 lavary

@MattWohler i need that too because i use SBAdmin template that use nav-second-level > nav-third-level .. thanks :)

fer-ri avatar Dec 03 '14 02:12 fer-ri

@MattWohler could you share your hack? or maybe some push request :)

fer-ri avatar Dec 03 '14 02:12 fer-ri

@lavary any update for this issue?

Thanks

fer-ri avatar Dec 03 '14 04:12 fer-ri

@ghprod my apologies, I would have sent you the fix this morning. I see you got impatient haha.. Good job.

MattWohler avatar Dec 03 '14 16:12 MattWohler

@MattWohler Hahhahah... :+1:

fer-ri avatar Dec 03 '14 16:12 fer-ri

@MattWohler seems like my pull request got bugs :package: need to cancel it .. :dancer:

fer-ri avatar Dec 25 '14 04:12 fer-ri

Anyone want to take a stab at this with a PR? Would anyone still benefit from this functionality?

dustingraham avatar Sep 27 '17 06:09 dustingraham

Let me ping here too :) I'm not playing laravel for long, but I faced unusual situation, where kind of depth retrieval was needed, because there is a need to place 'menu aliases'. Here's the brief of menu:

  • Menu element L1 (url /blabla)
  • About L1 (url /about)
    • Read about us (url /about) -> here comes the thing, same urls, L1 is menu item alias type ... I had to separate L1 and L2 in my template, so at first shot i tried: First row: {!! menu::get('xxx)->topMenu() !!} -> Level 1 is easy :) Second row: {!! menu::get('xxx')->submenu/siblings!} -> Level 2

Well, I couldn't fetch level2 menu items because there's no depth function, and as far the url is the same, the returned active item is the top-most so it fails when it comes to retrieve second row.

Finally I did quick test during mainmenu creation:

$active = $menu->active();
            if ($active) {
                if ($active->hasParent())
                    $l2 = $active->parent()->children();
                else
                    if ($active->hasChildren())
                        $l2 = $active->children();

                $nb = $menu->spawn('MainMenu_l2', $l2);
                foreach($l2 as $item)
                    $nb->add($item->title, $item->url());                

                $menu->second_level = $nb;
            }

There was a need to separate menu into two rows and display levels 1 and 2 separately, so I think it concerns this topic or I simply failed somewhere while trying to achieve this :)

Anyway - the first thing that I felt is missing was something related to depth.

bomkallo avatar May 15 '19 09:05 bomkallo

I hat the same problem. Here is my solution to help other people in this situation. I've created the following query to get my levels:

$getAllLevels = collect(DB::select(DB::raw("WITH RECURSIVE cte AS (
                                           SELECT 1 AS lvl, parent_id, id
                                           FROM site_menu_entries
                                           WHERE parent_id IS NULL
                                           UNION ALL
                                           SELECT lvl + 1, site_menu_entries.parent_id, site_menu_entries.id
                                           FROM site_menu_entries
                                           JOIN cte
                                             ON site_menu_entries.parent_id = cte.id
                                        )
                                        SELECT *  -- MAX(lvl) AS max_depth_of_tree
                                        FROM cte;")));

In the item iteration, I've added the following attribute to each item:

'depth' => $getAllLevels->firstWhere('id', $link->id)->lvl

Vmadmax avatar Dec 15 '19 11:12 Vmadmax