Skip to content

Menu Configuration

Diego Smania edited this page Apr 27, 2021 · 18 revisions

In this section we explain how to configure the menu items that will be available on your admin panel.

Menu

You can specify the set of menu items to display in the left sidebar and/or the top navbar. A menu item representing a link should have a text attribute and an url (or route) attribute. Also, and optionally, you can use the icon attribute to specify an icon from Font Awesome for every menu item. A single string instead of an array represents a header in the sidebar, a header is used to group items under a label. However, a header may also be represented by an array containing the header attribute. There is also a can attribute that can be used as a filter with the Laravel's built in Gate functionality. Even more, you can create a nested menu using the submenu attribute. Also, there are other options and attributes available that will be explained later.

Here is a basic example that will give you a quick overview of the menu configuration:

'menu' => [
    'MAIN NAVIGATION',
    [
        'text' => 'Blog',
        'url'  => 'admin/blog',
    ],
    [
        'text' => 'Pages',
        'url'  => 'admin/pages',
        'icon' => 'fas fa-fw fa-file',
    ],
    [
        'text'   => 'Show my website',
        'url'    => '/',
        'target' => '_blank',
    ],
    [
        'header' => 'ACCOUNT SETTINGS',
    ],
    [
        'text'  => 'Profile',
        'route' => 'admin.profile',
        'icon'  => 'fas fa-fw fa-user',
    ],
    [
        'text'  => 'Change Password',
        'route' => 'admin.password',
        'icon'  => 'fas fa-fw fa-lock',
    ],
],

On the next table, we give a summary of the available attributes for the menu items. Take in consideration that most of these attributes are optional and will be explained later with more details.

Attribute Description
active To define when the item should have the active style.
can Permissions of the item for use with Laravel's Gate.
classes To add custom classes to a menu item.
data An array with data-* attributes for the item.
header Text representing the name of a header (only for headers).
icon A font awesome icon for the item.
icon_color An AdminLTE color for the icon (info, primary, etc).
key An unique identifier key for reference the item.
label Text for a badge associated with the item.
label_color An AdminLTE color for the badge (info, primary, etc).
route A route name, usually used on link items.
shift [Deprecated] Classes to append to the list item (for shifting submenu items)
submenu Array with child items that enables nested menus definition.
text Text representing the name of the item.
topnav Bool to place the item on the top navbar.
topnav_right Bool to place the item in the right section of top navbar.
topnav_user Bool to place the item in the user menu.
url An URL path, normally used on link items.

Now, we going to review all of these attributes with more detail:

The active Attribute:

By default, a menu item is considered active if any of the following conditions holds:

  • The current path exactly matches the url attribute.
  • The current path without the query parameters matches the url attribute.
  • If it has a submenu containing an active menu item.

To override this default behavior, you can specify an active attribute containing an array with one or multiple URLs that will be used to search for a match. Even more, you can use asterisks and regular expressions on these URLs definitions in order to support some particular cases. To utilize a regex, you need to prefix your pattern with the regex: token and it will get evaluated automatically. The regex pattern will attempt to match the path of the URL returned by request()->path(), which returns the current URL without the domain name. At next, we can see an example that uses multiple URL definitions for the active state:

[
    'text'   => 'Pages',
    'url'    => 'pages',
    'active' => ['pages', 'content', 'content*', 'regex:@^content/[0-9]+$@']
]

In the previous case, the menu item will be considered active for all the next URLs:

  • http://my.domain.com/pages
  • http://my.domain.com/content
  • http://my.domain.com/content-user (because content*)
  • http://my.domain.com/content/1234 (because regex:@^content/[0-9]+$@)

The can Attribute:

You may use the can attribute if you want to conditionally show a menu item. This integrates with the Laravel's Gate functionality. If you need to conditionally show a header item, you need to wrap it in an array using the header attribute. You can also use multiple conditions entries with an array, check the next example for details:

[
    [
        'header' => 'BLOG',
        'can'    => 'manage-blog',
    ],
    [
        'text' => 'Add new post',
        'url'  => 'admin/blog/new',
        'can'  => ['add-blog-post', 'other-right'],
    ],
]

So, for the previous example the header will show only if the user has the manage-blog permission, and the link will show if the user has the add-blog-post or other-right permissions.

The classes Attribute:

This attribute provides a way to add custom classes to a particular menu item. The value should be a string with one or multiple class names, similar to the HTML class attribute. For example, you can make a colorful HEADER item centered on the left sidebar with the next definition:

[
    'header'   => 'account_settings',
    'classes'  => 'text-yellow text-bold text-center',
]

Or you can highlight an important link item with something like this:

[
    'text'     => 'Important Link',
    'url'      => 'important/link',
    'icon'     => 'fas fa-fw fa-exclamation-triangle',
    'classes'  => 'text-danger text-uppercase',
]

The data Attribute:

In order to add data-* attributes to your menu items, you can simply add an associative array called data to the item. Here is a basic example:

[
    'text' => 'New post',
    'url'  => 'admin/blog/new',
    'data' => [
        'test-one' => 'content-one',
        'test-two' => 'content-two',
    ],
]

Then, the previous menu item will be rendered as this:

<a class="nav-link" href="http://<domain>/admin/blog/new"
   data-test-one="content-one"
   data-test-two="content-two">
    <i class="far fa-fw fa-circle"></i>
    <p>New post</p>
</a>

The header Attribute:

This attribute is exclusive for header items, and the value is just his descriptive text. Headers are only available for the left sidebar and they provide a way to group items under a label. Example:

[
    'header'  => 'REPORTS',
]

A header item can also be represented with a single string, for example "REPORTS", but the array format provides a way to combine it with other attributes, like the can one. The header attribute supports translations, as explained on the Translations section.

The icon and icon_color Attributes:

This attribute is optional, and you will get an open circle if you leave it out. The available icons that you can use are those from Font Awesome. Just specify the name of the icon and it will appear in front of your menu item. The ìcon_color attribute provides a way to setup an AdminLTE color for the icon. Example:

[
    'text'       => 'profile',
    'url'        => 'user/profile',
    'icon'       => 'fas fa-fw fa-user',
    'icon_color' => 'primary',
]

The key Attribute:

In order to place an item dynamically you can use the key attribute, with this attribute you set an unique identifier for the item. Then, you can use this identifier later to add new items before or after the item represented by this key identifier. For more details, checkout the section Menu Configuration at Runtime.

The label and label_color Attributes:

The label attribute provides a way to setup a right aligned badge for the menu item. The label_color is used to configure the badge color, example:

[
    'text'        => 'pages',
    'url'         => 'admin/pages',
    'icon'        => 'far fa-fw fa-file',
    'label'       => 4,
    'label_color' => 'success',
]

The route Attribute:

You can use this attribute to assign a Laravel route name to a link item, if you choose to use this attribute, then don't combine it with the url attribute, for example:

[
    'text'  => 'Profile',
    'route' => 'admin.profile',
    'icon'  => 'fas fa-fw fa-user',
]

Even more, you can define a route with parameters using an array where the first value is the route name and the second value an array with the parameters, as shown next:

[
    'text'  => 'Profile',
    'route' => ['admin.profile', ['userID' => '673']],
    'icon'  => 'fas fa-fw fa-user',
]

The shift Attribute:

Important: This attribute will be dropped on the future. So, you should favor the usage of the classes attribute instead.

This attribute provides a way to inject classes into the list item for a given menu item. It's intended to allow the specification of custom margins on a submenu item to create an indented appearance. Example:

[
    'text'    => 'Personnel Management',
    'submenu' => [
        [
            'text'    => 'Invites',
            'shift'   => 'ml-3',
            'submenu' => [
                [
                    'text'  => 'View Invites',
                    'route' => 'invite.index',
                    'icon'  => 'fas  fa-users',
                    'shift' => 'ml-4',
                ],
            ],
        ],
    ],
]

The submenu Attribute:

This attribute provides a way to create a menu item containing child items. With this feature you can create nested menus. You can create a menu with items in the sidebar and/or the top navbar. Example:

[
    'text'    => 'menu',
    'icon'    => 'fas fa-fw fa-share',
    'submenu' => [
        [
            'text' => 'child 1',
            'url'  => 'menu/child1',
        ],
        [
            'text' => 'child 2',
            'url'  => 'menu/child2',
        ],
    ],
]

The text Attribute:

The value of this attribute is just the descriptive text for a menu item (except for headers). The text attribute supports translations, as explained on the Translations section.

The topnav, topnav_right and topnav_user Attributes:

It's possible to add menu items to the top navigation while the sidebar is enabled, you need to set the topnav attribute to true for this feature. Also, you can set the topnav_right attribute for put the item on the right side of the topnav or set the topnav_user attribute to place the menu item in the user menu (above the user-body).

Note: when the top navigation layout is enabled, all menu items will appear in the top navigation.

The url Attribute:

The value of this attribute should be the URL for a link item. You can use a full URL with the domain part or without it. Don't combine this attribute with the route attribute. Examples:

[
    'text' => 'profile',
    'url'  => 'http://my.domain.com/user/profile',
    'icon' => 'fas fa-fw fa-user',
],
[
    'text' => 'change_password',
    'url'  => 'admin/settings',
    'icon' => 'fas fa-fw fa-lock',
],

Special Menu Items

In this section we introduce some special menu items available for the sidebar and/or the top navbar.

Navbar Search

It's possible to add a search input in the top navbar using a menu item with the following configuration of attributes:

[
    'type'         => 'navbar-search',
    'text'         => 'search',        // Placeholder for the underlying input.
    'topnav_right' => true,            // Or "topnav => true" to place on the left.
    'url'          => 'navbar/search', // The url used to submit the data ('#' by default).
    'method'       => 'post',          // 'get' or 'post' ('get' by default).
    'input_name'   => 'searchVal',     // Name for the underlying input ('adminlteSearch' by default).
    'id'           => 'navbarSearch'   // ID attribute for the underlying input (optional).
]

Important: For package versions under v3.6.0 you need to use the legacy configuration replacing type => 'navbar-search' by search => true. However, you should note that legacy support will be discarded on the future.

For the previous definition, you may define a route and a controller to catch the submitted keywords, as shown below:

Route::match(
    ['get', 'post'],
    '/navbar/search',
    'SearchController@showNavbarSearchResults'
);
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;

class SearchController extends Controller
{
    ...

    /**
     * Show the navbar search results.
     *
     * @param Request $request
     * @return View
     */
    public function showNavbarSearchResults(Request $request)
    {
        // Check that the search keyword is present.

        if (! $request->filled('searchVal')) {
            return back();
        }

        // Get the search keyword.

        $keyword = $request->input('searchVal');

        Log::info("A navbar search was triggered with next keyword => {$keyword}");

        // TODO: Create the search logic and return adequate response (maybe a view
        // with the results).
        // ...
    }

    ...
}

Sidebar Search

It's possible to place a custom search input in your sidebar menu using an item with the following configuration of attributes:

[
    'type'       => 'sidebar-custom-search',
    'text'       => 'search',         // Placeholder for the underlying input.
    'url'        => 'sidebar/search', // The url used to submit the data ('#' by default).
    'method'     => 'post',           // 'get' or 'post' ('get' by default).
    'input_name' => 'searchVal',      // Name for the underlying input ('adminlteSearch' by default).
    'id'         => 'sidebarSearch'   // ID attribute for the underlying input (optional).
]

Important: For package versions under v3.6.0 you need to use the legacy configuration replacing type => 'sidebar-custom-search' by search => true. However, you should note that legacy support will be discarded on the future.

For the previous definition, you may define a route and a controller to catch the submitted keywords as explained on the previous navbar search example.

Sidebar Search Over Menu Items

Important: Available only for package versions >= v3.6.0.

It's also possible to place a search input in your sidebar menu that will automatically search over the available menu items using the following configuration of attributes:

[
    'type' => 'sidebar-menu-search',
    'text' => 'search',           // Placeholder for the underlying input.
    'id'   => 'sidebarMenuSearch' // ID attribute for the underlying input (optional).
]

Note the purpose of this item is to search over the set of available menu items in your sidebar and display the results automatically. It will not submit anything, so you don't need a route/controller definition for this item. Check the next image for an overview:

Sidebar-Menu-Search

Navbar Fullscreen Widget

Important: Available only for package versions >= v3.6.0.

It's possible to place a full screen widget button in your top navbar using the following configuration of attributes:

[
    'type'         => 'fullscreen-widget',
    'topnav_right' => true, // Or "topnav => true" to place on the left.
]

You should note the widget is automatically handled by the underlying AdminLTE template and there is no extra configuration for it.

Custom Menu Filters

You can set the filters you want to include for rendering the menu using the filters configuration of the config file. You can add your own filters to this array after you've created them. You can comment out the GateFilter if you don't want to use Laravel's built in Gate functionality. The current default set of menu filters is:

'filters' => [
    JeroenNoten\LaravelAdminLte\Menu\Filters\HrefFilter::class,
    JeroenNoten\LaravelAdminLte\Menu\Filters\SearchFilter::class,
    JeroenNoten\LaravelAdminLte\Menu\Filters\ActiveFilter::class,
    JeroenNoten\LaravelAdminLte\Menu\Filters\ClassesFilter::class,
    JeroenNoten\LaravelAdminLte\Menu\Filters\GateFilter::class,
    JeroenNoten\LaravelAdminLte\Menu\Filters\LangFilter::class,
    JeroenNoten\LaravelAdminLte\Menu\Filters\DataFilter::class,
],

If you need to use a custom menu filter, you can add your own menu filters to the previous array. This can be useful, for example, when you are using a third-party package for authorization (instead of the Laravel's Gate functionality).

In order to provide more details, we going to show an example of how you can configure the Laratrust Package. Start by creating your custom filter implementation:

<?php

namespace MyApp;

use JeroenNoten\LaravelAdminLte\Menu\Filters\FilterInterface;
use Laratrust\Laratrust;

class MyMenuFilter implements FilterInterface
{
    public function transform($item)
    {
        if (isset($item['permission']) && ! Laratrust::isAbleTo($item['permission'])) {
            $item['restricted'] = true;
        }

        return $item;
    }
}

And then add the following configuration to the config/adminlte.php file:

'filters' => [
    ...
    JeroenNoten\LaravelAdminLte\Menu\Filters\ActiveFilter::class,
    JeroenNoten\LaravelAdminLte\Menu\Filters\HrefFilter::class,
    JeroenNoten\LaravelAdminLte\Menu\Filters\ClassesFilter::class,
    // Comment next line out to remove the Gate filter.
    //JeroenNoten\LaravelAdminLte\Menu\Filters\GateFilter::class,
    MyApp\MyMenuFilter::class,
]

Menu Configuration at Runtime

It is also possible to configure the menu at runtime, for example in the boot method of any service provider or from a controller. You can add new menu items at the end of the menu, before or after a specific menu item, and also inside a menu item as a submenu item. You can use this feature if your menu is not static, for example when it depends on your database or the locale configuration.

It is also possible to combine both approaches, a static configured menu with dynamics modifications. The menu will simply be concatenated and the order of the service providers will determine the order in the menu.

The available menu builder methods are:

  • add(...$newItems)

    Adds one or multiple menu items, you can use the item's attributes to place the item/s in the sidebar or the topnav menus (right, left or user menu).

  • addAfter($itemKey, ...$newItems)

    Adds one or multiple menu items after a specific menu item (distinguished by his key attribute).

  • addBefore($itemKey, ...$newItems)

    Adds one or multiple menu items before a specific menu item (distinguished by his key attribute).

  • addIn($itemKey, ...$newItems)

    Adds one or multiple menu items inside a specific menu item (distinguished by his key attribute) as submenu or child item/s.

  • remove($itemKey)

    Removes one specific menu item (distinguished by his key attribute).

  • itemKeyExists($itemKey)

    Checks if a specific menu item exists, searched by the key attribute.

On the next example we going to give a basic overview of how to use the methods. First, we add a key attribute to a particular menu item.

[
    'key'  => 'pages',
    'text' => 'Pages',
    'url'  => 'admin/pages',
    'icon' => 'far fa-fw fa-file',
],

Then, we going to add the next menu items.

  1. Account Settings after Pages
  2. Notifications inside Account Settings
  3. Profile before Notifications

So, after listening for the BuildingMenu event dispatched by this package, we can write the next lines in order to add the mentioned new items:

$events->listen(BuildingMenu::class, function (BuildingMenu $event) {

    $event->menu->addAfter('pages', [
        'key' => 'account_settings',
        'header' => 'Account Settings',
    ]);

    $event->menu->addIn('account_settings', [
        'key' => 'account_settings_notifications',
        'text' => 'Notifications',
        'url' => 'account/edit/notifications',
    ]);

    $event->menu->addBefore('account_settings_notifications', [
        'key' => 'account_settings_profile',
        'text' => 'Profile',
        'url' => 'account/edit/profile',
    ]);
});

The event-based approach is used to make sure that the code that builds the menu runs only when the admin panel is actually displayed, and not on every request.

Config on Service Provider

To configure the menu at runtime on a particular service provider, just register a handler or callback for the MenuBuilding event, for example, in the boot() method:

use Illuminate\Contracts\Events\Dispatcher;
use JeroenNoten\LaravelAdminLte\Events\BuildingMenu;

class AppServiceProvider extends ServiceProvider
{
    public function boot(Dispatcher $events)
    {
        $events->listen(BuildingMenu::class, function (BuildingMenu $event) {
            // Add some items to the menu...
            $event->menu->add('MAIN NAVIGATION');
            $event->menu->add([
                'text' => 'Blog',
                'url' => 'admin/blog',
            ]);
        });
    }
}

The attributes for a menu item are the same explained previously. Here is a more practical example that uses translations and the database:

public function boot(Dispatcher $events)
{
    $events->listen(BuildingMenu::class, function (BuildingMenu $event) {

        $event->menu->add(trans('menu.pages'));

        $items = Page::all()->map(function (Page $page) {
            return [
                'text' => $page['title'],
                'url' => route('admin.pages.edit', $page)
            ];
        });

        $event->menu->add(...$items);
    });
}