MenuCRUD
MenuCRUD copied to clipboard
[Discussion] Menu Sections
I have closed PR #23 as it is rough idea and not best full feature wise. We should discuss a little more on how we can best implement a multi-menu option. I have a rough draft on my current application which I will be using until we have better option (see gif below) I will share code later if enough interest in it however there are some bugs with it that I am working on and the UX is a bit clunky. Improvements for it is appreciated.
I was looking to include a dynamic menu so I can quickly add in the menu the new pages that I create and I came up with this solution using your get Tree method.
Just thought maybe somebody else tries to do something similar and this might help them.
Also, let me know your thoughts on this, how can we go more than 2 levels deep? As currently, my 3rd level will not show up in the menu.
Also, please NOTE that I have added an extra field in my MenuCRUD, called "icon" so I can add icons to my menus.
This code goes directly in the sidebar.blade.php where you should define your menu items.
@foreach(App\Models\MenuItem::getTree() as $menuItem)
@if($menuItem->children->isEmpty())
<li>
<a href="{{$menuItem->url()}}">
@if($menuItem->icon)
<i class="fa {{$menuItem->icon}}"></i>
@endif
<span>{{$menuItem->name}}</span>
</a>
</li>
@else
<li class="treeview">
<a href="#">
@if($menuItem->icon)
<i class="fa {{$menuItem->icon}}"></i>
@endif
<span>{{$menuItem->name}}</span>
<i class="fa fa-angle-left pull-right"></i>
</a>
<ul class="treeview-menu">
@foreach($menuItem->children as $child)
<li>
<a href="{{$child->url()}}">
@if($child->icon)
<i class="fa {{$child->icon}}"></i>
@endif
<span>{{$child->name}}</span>
</a>
</li>
@endforeach
</ul>
</li>
@endif
@endforeach
@AbbyJanke it would be great to have the ability to create multiple menus as you suggest, eg Header menu, footer menu etc
@AbbyJanke @tabacitu mentioned the UI so possibly something like how Bolt do it?
Hi @AbbyJanke @tabacitu are there any plans to do this or is it something you would need a PR for?
@seandowney take a look at PR #23 (mentioned in first post) i had an idea of doing it but wasnt the most intuitive. It works but not super user friendly so if you have a better way really a PR would be great.
@AbbyJanke that's fair enough. I'll have a look and come back with an idea if I can improve on what you had done :+1: :-)
@seandowney , yup, I think it’s about time we add this functionality :-)
I think @AbbyJanke ’s idea of adding some tabs on top of the CRUD (and what you mentioned Bold do) is the way to go. I would add it on both the ListEntries screen, and on the Reorder screen, to make it more intuitive. And we’d only show the items of that menu, both in reorder and in listing. It would, however, require us to change the logic of reordering, to only take into account the current menu items, both for showing and for reordering...
I don’t think we need to store menu sections inside a database (ex: header menu, footer menu) and allow admins to add/remove menu sections. Since they can’t include those menus in code (only a developer can do that), that wouldn’t really make sense, and having a CRUD for menu sections would just make it more difficult to understand. I think a select_from_array
is enough - where the developer specifies the values. But that’s only if they copy-pasted it in their apps - which I hope they did. Not install as a composer package. So maybe something like:
class MenuItemCrudController extends CrudController
{
public $menus = [
'header' => 'Header',
'footer' => 'Footer',
];
public function setup()
{
//…
if (count($this->menus)) {
$this->crud->addField([ // select_from_array
'name' => ‘menu',
'label' => “Menu",
'type' => 'select_from_array',
'options' => $this->menus,
'allows_null' => false,
]);
}
//…
}
// ...
}
For the user, the only things that would change would be:
- tabs above the listing page
- tabs above the reordering page
- another field in the create&update forms
Out of curiosity - how do you guys use MenuCRUD - as a composer package, or copy-pasted in your project?
Thanks!
Thanks @tabacitu
I think I've used it as a composer package. Could there be a config for the menus?
return [
'menus' => [
'header' => 'Header',
'footer' => 'Footer',
],
];
I wonder if it would be possible to code a menu generator with arbitrary recursion depth. I don't know how many levels deep my menu's deepest leaf will be, but two levels is certainly not sufficient. I want to call a controller function recursively from a view that in turn calls the view recursively. Does that make any sense?
Hi @ssimo3lsuhsc - it makes sense to make your menu output recursive, yes. From a programming perspective. From a UX perspective though, I do not recommend going more than 2-3 levels deep. In my experience, it will look awful, and be more difficult to use. I know the intention is to make it as general as possible, but (again, in my experience) if you have a menu that's more than 2-3 levels deep, it's too deep, you should reorganise it.
That being said, I don't think your recursive function should live in a controller. It shoould live inside a view. It's ok to have functions inside views, if what they just echo stuff. So something like this:
@php
function echoMenuItemAndChildren($item) {}
@endphp
is perfectly fine in my opinion.
Hope it helps.
Are there any new plans/ideas for this? At the moment I need such a possibility to create header/footer menus and I am thinking about a possible workaround to achieve this in the short term.
What do you think about the following:
- Creating two subclasses
HeaderMenuItemCrudController
andFooterItemCrudController
that will inherit fromMenuItemCrudController
; - Both controller will still point to and use
MenuItem
; - Introducing a new column 'menu' (probably an enum with "header" and "footer") inside the database;
- Overriding the
list
operation to always filter the list by the newmenu
column in the subclasses like$this->crud->addClause('where', 'menu', '=', 'footer');
- Overriding the create operation to contain a hidden field with the
menu
value inserted;
Is there something else that I am missing that will not work properly? I believe the reordering should work properly this was.
Update: @tabacitu, what about using https://backpackforlaravel.com/docs/4.1/crud-buttons#adding-a-custom-button-with-javascript-to-the-top-stack to add a custom select element, which will do the distinction between the different menus (header, footer, etc.)? The only thing I cannot solve is how to send the "menu" to the setup operation. Any ideas?
Otherwise, it might be better to just send the selected menu as url parameter and the filtering will happen automatically. The only downside is that on opening the CRUD list all menu items (mixed) will be listed, so I should find a way to solve this.
Overall my updated idea will:
- Eliminate the need of creating additional CrudControllers
- Allow the developer to easily modify the list of all possible menus
- It can fallback to the current state where no such list of menus is provided, so the button won't show and a filtering won't be applied
I still have to think of the proper way to instruct the create
operation to automatically fill in the menu
value.
Update 2:
With few modifications to the MenuItemCrudController
and also MenuItem
, it works fine and did not require a big effort to do. If anyone is interested in my workaround solution, just tell me, so I can share the details.