Create menu objects server-sided without sweat for Front-End adoption.
You can install the package via composer:
composer require rspeekenbrink/laravel-menu
A default menu will already be registered and bound to the Menu
facade. You can add items to the menu like this:
Menu::add('itemName', '/');
// Menu::toArray() Output:
[
[
'name' => 'itemName',
'route' => '/',
'active' => true,
]
]
The itemName should be unique within the menu since this is the identifier of the item in the Menu.
The route can be an absolute route like '/dashboard/profile'
or a name of a route like 'dashboard.index'
for the automatic active state checking to work properly. If you want to use route names we recommend you to use Ziggy to convert the names to URLs in your front-end.
The active attribute is a boolean that will be true if the route matches the route of the current request (path or name wise).
To create nested items you could use the following:
Menu::add('dashboard', '/')->addChildren(function () {
Menu::add('stats', '/stats');
Menu::add('profile', '/profile');
});
// Menu::toArray() Output:
[
[
'name' => 'dashboard',
'route' => '/',
'active' => true,
'children' => [
[
'name' => 'dashboard.stats',
'route' => '/stats',
'active' => false,
],
[
'name' => 'dashboard.profile',
'route' => '/profile',
'active' => false,
]
]
]
]
You can pass attributes to the MenuItem to define values like Title or anything else you desire;
Menu::add('itemName', '/', ['title' => 'Dashboard', 'someAttribute' => 231, 'another' => 'value2']);
// Menu::toArray() Output:
[
[
'name' => 'itemName',
'route' => '/',
'active' => true,
'title' => 'Dashboard',
'someAttribute' => 231,
'another' => 'value2,
]
]
If you would like to add menu items conditionwise, for example only add a menu item if a user is logged in, you can do it like this:
Menu::addIf($conditionOrClosure, 'itemName', $route, $attributes);
Or pass a Auth Guard:
Menu::addIfCan('MyAuthGuard', 'itemName', $route, $attributes);
The main purpose of this package is to create Menu objects that can be adopted easily by the Front-End. One of the easiest ways to transfer the objects from the back to the front is by using InertiaJS.
Inertia::share([
'menu' => function () {
return Menu::toArray();
}
]);
Then for example in your inertia-vue layout template;
<template>
<nav>
<template v-for="(item, i) in $page.menu">
<template>
<li :class="item.active ? 'active' : ''"
@click="$inertia.visit(item.route, { preserveState: true })">
<span>{{ item.title }}</span>
</li>
</template>
<template v-if="item.children" v-for="(child, i) in item.children">
<li :class="child.active ? 'active' : ''"
@click="$inertia.visit(child.route, { preserveState: true })">
<span>{{ child.title }}</span>
</li>
</template>
</template>
</nav>
</template>
composer test
Please see CONTRIBUTING for details.
If you discover any security related issues, please email [email protected] instead of using the issue tracker.
The MIT License (MIT). Please see License File for more information.