awes-io/navigator

🧿 Build navigation or menu for Laravel and Awes.io. Unlimit complexity and depth of the menu.

v1.0.0 2019-07-31 08:13 UTC

This package is auto-updated.

Last update: 2024-09-29 05:42:23 UTC


README

Awes.io logo

Navigator

Laravel package that can easily create navigation menus of any complexity. With support for routing, permissions, sorting, rendering depth, active items marking and element searching.

Coverage report Last version Build status Downloads License CDN Ready laravel Last commit Analytics Hosted by Package Kit Patreon

Navigator Laravel

Table of Contents

Installation

Via Composer

$ composer require awes-io/navigator

The package will automatically register itself.

Quickstart

Let's firstly create basic navigation, which covers most of the use cases.

Create navigation configuration file:

// config/navigation.php

return [
    [
        'name' => 'Projects',
        'route' => 'projects.index', // route must exist or item will be hidden
        'children' => 
        [
            [
                'name' => 'New projects',
                'link' => '/projects/new', // you can use direct links
            ]
        ]
    ],
    [
        'name' => 'Packages',
        'route' => 'packages.index',
    ]
];

Next, let's build our menu somewhere in the controller and pass it to a view:

$menu = buildMenu(config('navigation'));
return view('menu', compact('menu'));

And finally implement basic rendering logic:

// menu.blade.php
@foreach($menu as $item)
  <ul>
    <li>
        @if($item->link())
            <a href="{{$item->link()}}">
              @if($item->isActive()) ACTIVE @endif {{$item->name}}
            </a>
        @else
            {{$item->name}}
        @endif
    </li>
    @if($item->hasChildren())
       @include('menu', ['menu' => $item->children()])
    @endif
  </ul>
@endforeach

That's all that simple!

Configuration

You can publish the config file:

php artisan vendor:publish --provider="AwesIO\Navigator\NavigatorServiceProvider" --tag="config"

And rename any options keys, which are used to get respective data from the menu config:

// navigator.php config
'keys' => [
    'depth' => 'depth', // rendering depth
    'order' => 'order', // ordering by parameter
    'children' => 'children', // sub menu items
    'route' => 'route', // route name
    'link' => 'link', // item link url
    'title' => 'name', // item title
    'attr' => 'attr', // additional item attributes
],

As well as use alternative menu settings for parsing and rendering:

// navigator.php config
'keys' => [
    ...
    'children' => 'other-children', // alternative sub menu items
    ...
],

// navigation.php
'menu' => [
    [
        ...
        'children' => [
        ...
        'other-children' => [
        ...
]

Navigator::buildMenu(config('navigation.menu')); // will now parse menu using 'other-children'

You can achieve the same effect dynamically, via mappings mentioned above:

$menu = buildMenu(config('navigation.menu'), [], ['children' => 'other-children']);

Note that we now use the global helper method buildMenu().

Usage

use AwesIO\Navigator\Facades\Navigator;

$menu = Navigator::buildMenu(config('navigation.menu'), ['depth' => 2], [], function ($item) {
    $item->put('meta', $item->get('title') . ' / ' . $item->get('link'));
});

// using helper, rendering depth set via config as a second parameter
$menu = buildMenu(config('navigation.menu'), ['depth' => 2], [], function ($item) {});

The first parameter is the menu config in the form of an array:

// navigation.php
return [
    'menu' => [
        [
            'title' => 'Products', // menu item's title
            'route' => 'products.index', // route name for URL generation
            'order' => 1, // parameter to determine the order
            'depth' => 1, // depth for the recursive generation of descendants
            'children' => 
            [
                [
                    'id' => 1, // custom id which overwrites auto-generated one
                    'title' => 'Catalog',
                    'link' => 'products/catalog', // explicit relative path for link URL 
                ],
                [
                    'title' => 'Support',
                    'route' => 'products.support'
                ]
            ]
        ],
        [
            'title' => 'Contact us',
            'route' => 'contacts',
            'order' => 2,
        ],
    ]
];

Second is config, the third one is mappings for configuration parameters (described above), last is a callback, which will be applied to each menu item.

Some helpful methods

Determine if the node has any children and retrieve them:

$menu->hasChildren();
$menu->children();

Get a link URL for a node:

$menu->link();

Determine if a node is currently selected and active:

$menu->isActive();

Get a currently active node and its id:

$menu->getActive();
$menu->getActiveId();

Find a node by its id:

$menu->findById($id);

Menu rendering example

// somewhere in a controller
$menu = Navigator::buildMenu(config('navigation.menu'));
return view('view', compact('menu'));

// view.blade.php
@extends('main')

@section('content')
    @include('menu', ['menu' => $menu])
@endsection

// menu.blade.php
@foreach($menu as $item)
  <ul>
    <li>
        @if($item->link())
            <a href="{{$item->link()}}">{{$item->title}}</a>
        @else
            {{$item->title}}
        @endif
    </li>
    @if($item->hasChildren())
       @include('menu', ['menu' => $item->children()])
    @endif
  </ul>
@endforeach

Permissions

If the user is not authorized to access some of the menu routes, they'll be automatically hidden based on existing permissions:

Route::group(['middleware' => ['can:manage users']], function () {
    Route::get('/', 'RoleController@index')->name('admin.roles.index');
});

// will be excluded from the menu for non-admin users
[
    'name' => __('navigation.security'),
    'icon' => 'twousers',
    'route' => 'admin.roles.index',
],

Testing

The coverage of the package is Coverage report.

You can run the tests with:

composer test

Contributing

Please see contributing.md for details and a todolist.

Credits

License

MIT