├── .gitignore ├── resources └── views │ └── menus │ ├── simple │ ├── heading.blade.php │ ├── parent.blade.php │ ├── item.blade.php │ └── menu.blade.php │ ├── sbadmin2 │ ├── heading.blade.php │ ├── menu-2.blade.php │ ├── item-2.blade.php │ ├── item.blade.php │ ├── parent.blade.php │ └── menu.blade.php │ ├── admin-lte │ ├── menus-dropdown.blade.php │ ├── menus-dropdown-item.blade.php │ ├── menus.blade.php │ └── item.blade.php │ └── bs-nav-stacked │ ├── menu.blade.php │ └── item.blade.php ├── screenshoot.png ├── src ├── Facades │ └── Menu.php ├── Modifiers │ └── NavFullUrl.php ├── Renders │ └── NavViewRender.php ├── LaravelNavigator.php ├── MenuServiceProvider.php ├── Concerns │ └── NavCollectionManage.php └── Menu.php ├── helpers └── helpers.php ├── config └── laravel-menu.php ├── composer.json └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | /vendor 2 | -------------------------------------------------------------------------------- /resources/views/menus/simple/heading.blade.php: -------------------------------------------------------------------------------- 1 |
  • {{ $nav->getText() }}
  • 2 | -------------------------------------------------------------------------------- /screenshoot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nurmanhabib/laravel-menu/HEAD/screenshoot.png -------------------------------------------------------------------------------- /resources/views/menus/sbadmin2/heading.blade.php: -------------------------------------------------------------------------------- 1 |
  • {{ $nav->getText() }}
  • 2 | -------------------------------------------------------------------------------- /resources/views/menus/admin-lte/menus-dropdown.blade.php: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /resources/views/menus/sbadmin2/menu-2.blade.php: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /resources/views/menus/bs-nav-stacked/menu.blade.php: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /src/Facades/Menu.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |

    {{ $item->getText() }}

    5 |
    6 | 7 | -------------------------------------------------------------------------------- /resources/views/menus/sbadmin2/item-2.blade.php: -------------------------------------------------------------------------------- 1 | @if ($nav->hasChild()) 2 | @include('menus::sbadmin2.parent', ['level' => 'third']) 3 | @else 4 |
  • 5 | 6 | {{ $nav->getText() }} 7 | 8 |
  • 9 | @endif 10 | -------------------------------------------------------------------------------- /resources/views/menus/simple/parent.blade.php: -------------------------------------------------------------------------------- 1 |
  • 2 | @if ($nav->isActive()) 3 | {{ $nav->getText() }} 4 | @else 5 | {{ $nav->getText() }} 6 | @endif 7 | @include('menus::simple.menu', ['menu' => $nav->getChild()]) 8 |
  • 9 | -------------------------------------------------------------------------------- /resources/views/menus/admin-lte/menus.blade.php: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /helpers/helpers.php: -------------------------------------------------------------------------------- 1 | get($name) : app('menu'); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /resources/views/menus/simple/item.blade.php: -------------------------------------------------------------------------------- 1 | @if ($nav->hasChild()) 2 | @include('menus::simple.parent') 3 | @else 4 | @if ($nav->isActive()) 5 |
  • {{ $nav->getText() }}
  • 6 | @else 7 |
  • {{ $nav->getText() }}
  • 8 | @endif 9 | @endif 10 | -------------------------------------------------------------------------------- /resources/views/menus/sbadmin2/item.blade.php: -------------------------------------------------------------------------------- 1 | @if ($nav->hasChild()) 2 | @include('menus::sbadmin2.parent', ['level' => 'second']) 3 | @else 4 |
  • 5 | 6 | {{ $nav->getText() }} 7 | 8 |
  • 9 | @endif 10 | -------------------------------------------------------------------------------- /resources/views/menus/bs-nav-stacked/item.blade.php: -------------------------------------------------------------------------------- 1 | @if ($nav->hasChild()) 2 | {{-- No support parent --}} 3 | @else 4 | @if ($nav->isActive()) 5 | 6 | @else 7 |
  • {{ $nav->getText() }}
  • 8 | @endif 9 | @endif 10 | -------------------------------------------------------------------------------- /resources/views/menus/sbadmin2/parent.blade.php: -------------------------------------------------------------------------------- 1 |
  • 2 | 3 | @if ($level == 'second') 4 | {{ $nav->getText() }} 5 | @else 6 | {{ $nav->getText() }} 7 | @endif 8 | 9 | 10 | @include('menus::sbadmin2.menu-2', ['menu' => $nav->getChild(), 'level' => $level]) 11 |
  • 12 | -------------------------------------------------------------------------------- /resources/views/menus/simple/menu.blade.php: -------------------------------------------------------------------------------- 1 | 12 | -------------------------------------------------------------------------------- /resources/views/menus/sbadmin2/menu.blade.php: -------------------------------------------------------------------------------- 1 | 12 | -------------------------------------------------------------------------------- /src/Modifiers/NavFullUrl.php: -------------------------------------------------------------------------------- 1 | to(parent::getUrl() ?: '/'); 12 | } 13 | 14 | public function toArray() 15 | { 16 | return array_merge(parent::toArray(), [ 17 | 'url' => $this->getUrl() 18 | ]); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /config/laravel-menu.php: -------------------------------------------------------------------------------- 1 | [ 5 | 'view' => 'simple', 6 | ], 7 | 8 | 'views' => [ 9 | 'simple' => 'menus::simple.menu', 10 | 'bs-nav-stacked' => 'menus::bs-nav-stacked.menu', 11 | 'sbadmin2' => 'menus::sbadmin2.menu', 12 | 'adminto' => 'adminto::menus.sidebar.menu', 13 | 'admin-lte' => 'menus::admin-lte.menus', 14 | ], 15 | 16 | // 'menus' => [ 17 | // 'sidebar' => [ 18 | // 'view' => 'sb-nav-stacked' 19 | // ] 20 | // ] 21 | ]; 22 | -------------------------------------------------------------------------------- /src/Renders/NavViewRender.php: -------------------------------------------------------------------------------- 1 | view = $view; 18 | } 19 | 20 | public function render(NavCollection $menu) 21 | { 22 | if (!view()->exists($this->view)) { 23 | return 'View [' . $this->view . '] not found'; 24 | } 25 | 26 | return view($this->view, compact('menu')); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/LaravelNavigator.php: -------------------------------------------------------------------------------- 1 | setView(menu()->getDefaultView()); 18 | } 19 | 20 | public function setView($view) 21 | { 22 | $view = app('menu')->getView($view); 23 | 24 | $this->menu->setRenderer(new NavViewRender($view)); 25 | 26 | return $this; 27 | } 28 | 29 | public function renderView($view) 30 | { 31 | return $this->render(new NavViewRender($view)); 32 | } 33 | 34 | public function getMenu() 35 | { 36 | $this->transform(function (Nav $nav) { 37 | return new NavFullUrl($nav); 38 | }); 39 | 40 | return parent::getMenu(); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nurmanhabib/laravel-menu", 3 | "description": "Make it easy to create navigation menus on Laravel", 4 | "type": "library", 5 | "require": { 6 | "laravel/framework": ">5.0", 7 | "nurmanhabib/navigator": "^5.0.3" 8 | }, 9 | "license": "MIT", 10 | "keywords": [ 11 | "laravel menu", 12 | "laravel navigation", 13 | "navigation", 14 | "navigator", 15 | "menu", 16 | "sidebar", 17 | "navbar" 18 | ], 19 | "authors": [ 20 | { 21 | "name": "Habib Nurrahman", 22 | "email": "nurmanhabib@yahoo.co.id" 23 | } 24 | ], 25 | "autoload": { 26 | "psr-4": { 27 | "Nurmanhabib\\LaravelMenu\\": "src/" 28 | } 29 | }, 30 | "extra": { 31 | "laravel": { 32 | "providers": [ 33 | "Nurmanhabib\\LaravelMenu\\MenuServiceProvider" 34 | ], 35 | "aliases": { 36 | "Menu": "Nurmanhabib\\LaravelMenu\\Facades\\Menu" 37 | } 38 | } 39 | }, 40 | "minimum-stability": "stable" 41 | } 42 | -------------------------------------------------------------------------------- /src/MenuServiceProvider.php: -------------------------------------------------------------------------------- 1 | registerConfig(); 12 | $this->registerConainer(); 13 | $this->registerHelpers(); 14 | $this->registerViews(); 15 | } 16 | 17 | protected function registerConfig() 18 | { 19 | $this->publishes([ 20 | __DIR__.'/../config/laravel-menu.php' => config_path('laravel-menu.php') 21 | ], 'config'); 22 | 23 | $this->mergeConfigFrom(__DIR__.'/../config/laravel-menu.php', 'laravel-menu'); 24 | } 25 | 26 | protected function registerConainer() 27 | { 28 | $this->app->singleton('menu', function ($app) { 29 | $menu = new Menu; 30 | 31 | foreach ($app['config']->get('laravel-menu.views', []) as $alias => $view) { 32 | $menu->registerView($alias, $view); 33 | } 34 | 35 | return $menu; 36 | }); 37 | } 38 | 39 | protected function registerHelpers() 40 | { 41 | require_once __DIR__.'/../helpers/helpers.php'; 42 | } 43 | 44 | protected function registerViews() 45 | { 46 | $this->loadViewsFrom(__DIR__.'/../resources/views/menus', 'menus'); 47 | 48 | $this->publishes([ 49 | __DIR__.'/../resources/views/menus' => resource_path('views/vendor/menus') 50 | ], 'views'); 51 | } 52 | 53 | public function register() 54 | { 55 | 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/Concerns/NavCollectionManage.php: -------------------------------------------------------------------------------- 1 | navStack[] = $navigator; 19 | 20 | return $this; 21 | } 22 | 23 | public function clearCurrent() 24 | { 25 | array_pop($this->navStack); 26 | 27 | return $this; 28 | } 29 | 30 | /** 31 | * @return NavCollection 32 | */ 33 | public function getCurrent() 34 | { 35 | return end($this->navStack); 36 | } 37 | 38 | public function arrays(array $items) 39 | { 40 | return $this->getCurrent()->addArrays($items); 41 | } 42 | 43 | public function array(array $item) 44 | { 45 | return $this->getCurrent()->addArray($item); 46 | } 47 | 48 | public function logout($text = 'Logout', $url = 'logout', $icon = null) 49 | { 50 | return $this->link($text, $url, $icon, 'POST'); 51 | } 52 | 53 | public function link($text, $url = '#', $icon = null, $method = 'GET') 54 | { 55 | return $this->getCurrent()->addLink($text, $url, $icon)->setData(compact('method')); 56 | } 57 | 58 | public function heading($text) 59 | { 60 | return $this->getCurrent()->addHeading($text); 61 | } 62 | 63 | public function home($text = 'Home', $url = '#', $icon = null) 64 | { 65 | return $this->getCurrent()->addHome($text, $url, $icon); 66 | } 67 | 68 | public function separator() 69 | { 70 | return $this->getCurrent()->addSeparator(); 71 | } 72 | 73 | public function dropdown($text, callable $callback, $icon = null, $url = '#') 74 | { 75 | return $this->parent($text, $callback, $icon, $url); 76 | } 77 | 78 | public function parent($text, callable $callback, $icon = null, $url = '#') 79 | { 80 | $parent = $this->getCurrent()->addParent($text, function () {}, $icon, $url); 81 | 82 | $this->setCurrent($child = $parent->getChild()); 83 | 84 | $callback($child); 85 | 86 | $this->clearCurrent(); 87 | 88 | return $parent; 89 | } 90 | 91 | public function add(Nav $nav) 92 | { 93 | return $this->getCurrent()->add($nav); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /resources/views/menus/admin-lte/item.blade.php: -------------------------------------------------------------------------------- 1 | @if ($item->getType() == 'heading') 2 | 3 | @else 4 | @if ($item->hasChild()) 5 | 18 | @else 19 | 51 | @endif 52 | @endif 53 | -------------------------------------------------------------------------------- /src/Menu.php: -------------------------------------------------------------------------------- 1 | navigators = new Collection($navigators); 36 | $this->renders = new Collection; 37 | $this->views = new Collection; 38 | } 39 | 40 | /** 41 | * @param string $name 42 | * @param callable $callback 43 | * @return LaravelNavigator 44 | */ 45 | public function make($name = 'default', callable $callback = null) 46 | { 47 | $navigator = new LaravelNavigator($menu = new NavCollection); 48 | 49 | $this->navigators->put($name, $navigator); 50 | 51 | $this->setCurrent($menu); 52 | 53 | if ($callback) { 54 | $callback($menu); 55 | } 56 | 57 | $this->clearCurrent(); 58 | 59 | return $navigator; 60 | } 61 | 62 | /** 63 | * @param string $name 64 | * @param array $items 65 | * @return LaravelNavigator 66 | */ 67 | public function makeFromArray($name = 'default', array $items = []) 68 | { 69 | $factory = new ArrayNavCollectionFactory($items); 70 | 71 | $navigator = new LaravelNavigator($menu = $factory->createNavCollection()); 72 | 73 | $this->navigators->put($name, $navigator); 74 | 75 | return $navigator; 76 | } 77 | 78 | /** 79 | * @return Collection 80 | */ 81 | public function all() 82 | { 83 | return $this->navigators; 84 | } 85 | 86 | public function render($name = 'default') 87 | { 88 | return $this->get($name)->render(); 89 | } 90 | 91 | /** 92 | * @param string $name 93 | * @param callable|null $callback 94 | * @return LaravelNavigator 95 | */ 96 | public function get($name = 'default', callable $callback = null) 97 | { 98 | if (!$this->navigators->has($name)) { 99 | throw new \Exception('Menu not found'); 100 | } 101 | 102 | $navigator = $this->navigators->get($name); 103 | 104 | if ($callback) { 105 | $callback($navigator->getOriginalMenu()); 106 | } 107 | 108 | return $navigator; 109 | } 110 | 111 | /** 112 | * @param string $alias 113 | * @param string $view 114 | * @return Menu 115 | */ 116 | public function registerView($alias, $view) 117 | { 118 | $this->views->put($alias, $view); 119 | 120 | return $this; 121 | } 122 | 123 | public function hasView($view) 124 | { 125 | return $this->views->has($view); 126 | } 127 | 128 | public function getView($view) 129 | { 130 | return $this->views->get($view, $view); 131 | } 132 | 133 | public function getDefaultView() 134 | { 135 | return config('laravel-menu.default.view'); 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Welcome to Laravel Menu! 2 | 3 | Generate multi navigation menus with unique names, can be displayed anywhere. Custom templating. Support Laravel 5, 6, 7. 4 | 5 | ![Alt image](screenshoot.png) 6 | 7 | ------ 8 | 9 | ## Installation 10 | 11 | #### Installation with Composer 12 | 13 | Simply execute the following command 14 | 15 | ``` 16 | composer require nurmanhabib/laravel-menu 17 | ``` 18 | 19 | 20 | 21 | #### Register Service Provider and Facade 22 | 23 | Add `Nurmanhabib\LaravelMenu\MenuServiceProvider` to the file in `config/app.php` in array with key `providers`. 24 | 25 | ```php 26 | 'providers' => [ 27 | ..., 28 | ..., 29 | 30 | Nurmanhabib\LaravelMenu\MenuServiceProvider::class, 31 | ], 32 | ``` 33 | 34 | 35 | 36 | Add `Nurmanhabib\LaravelMenu\Facades\Menu` to the file in `config/app.php` in array with key `aliases`. 37 | 38 | 39 | ```php 40 | 'aliases' => [ 41 | ..., 42 | ..., 43 | 44 | 'Menu' => Nurmanhabib\LaravelMenu\Facades\Menu::class, 45 | ], 46 | ``` 47 | 48 | ------ 49 | 50 | ## Quick Example 51 | 52 | You can create in the routes files, middleware, or service providers that you custom yourself as needed. 53 | 54 | ```php 55 | setIcon('fas fa-home'); 59 | Menu::link('Article', 'articles')->setIcon('fas fa-newspaper') 60 | ->setData([ 61 | 'badge' => [ 62 | 'type' => 'warning', 63 | 'text' => '16' 64 | ] 65 | ]); 66 | 67 | Menu::link('Comment', 'comments')->setIcon('fas fa-comments') 68 | ->setData([ 69 | 'badge' => [ 70 | 'type' => 'primary', 71 | 'text' => 'New' 72 | ] 73 | ]); 74 | 75 | Menu::dropdown('Services', function () { 76 | Menu::link('Service 1', 'services/one'); 77 | Menu::link('Service 2', 'services/two'); 78 | }); 79 | 80 | Menu::heading('Account'); 81 | 82 | Menu::link('Change Password')->setIcon('fas fa-key'); 83 | Menu::logout()->setIcon('fas fa-sign-out-alt'); 84 | }); 85 | 86 | ``` 87 | 88 | 89 | ```php 90 | setData(['method' => 'POST']); 102 | }); 103 | ``` 104 | 105 | 106 | ### Make From Array 107 | 108 | You might be able to make it from another data source (for example: a database) and then process it into array data and turn it into a menu. 109 | 110 | ```php 111 | 'Home', 116 | 'url' => '/' 117 | ], 118 | [ 119 | 'text' => 'Berita', 120 | 'url' => 'berita', 121 | 'match' => '/berita*' 122 | ], 123 | [ 124 | 'type' => 'separator' 125 | ], 126 | [ 127 | 'text' => 'Kategori', 128 | 'child' => [ 129 | [ 130 | 'text' => 'Teknologi', 131 | 'url' => 'kategori/teknologi' 132 | ], 133 | [ 134 | 'text' => 'Otomotif', 135 | 'url' => 'kategori/otomotif' 136 | ], 137 | [ 138 | 'text' => 'Lifestyle', 139 | 'child' => [ 140 | [ 141 | 'text' => 'Pria', 142 | 'url' => 'lifestyle-pria' 143 | ], 144 | [ 145 | 'text' => 'Wanita', 146 | 'url' => 'lifestyle-wanita' 147 | ], 148 | ] 149 | ], 150 | ] 151 | ], 152 | [ 153 | 'type' => 'heading', 154 | 'text' => 'Configuration' 155 | ], 156 | [ 157 | 'text' => 'Account', 158 | 'child' => [ 159 | [ 160 | 'text' => 'Change Password', 161 | 'url' => 'change-password' 162 | ], 163 | [ 164 | 'text' => 'Logout', 165 | 'url' => 'logout' 166 | ], 167 | ] 168 | ], 169 | ]; 170 | 171 | Menu::makeFromArray('sidebar', $items); 172 | 173 | // or 174 | 175 | Menu::make('sidebar', function () use ($items) { 176 | Menu::arrays($items); 177 | }); 178 | 179 | ``` 180 | 181 | 182 | 183 | #### Set View 184 | 185 | ```php 186 | Menu::get('sidebar')->setView('admin-lte'); 187 | ``` 188 | 189 | 190 | #### Render to View 191 | 192 | ```html 193 | {!! Menu::get('sidebar') !!} 194 | ``` 195 | 196 | 197 | You can also call with the `menu()` helpers 198 | 199 | 200 | ```html 201 | {!! menu()->get('sidebar') !!} 202 | ``` 203 | 204 | or 205 | 206 | ```html 207 | {!! menu('sidebar') !!} 208 | ``` 209 | 210 | 211 | 212 | ## Custom View 213 | 214 | To be able to customize the navigation with view 215 | 216 | ```php 217 | Menu::get('sidebar')->setView('view.name'); 218 | ``` 219 | 220 | Available default views: 221 | 222 | ```php 223 | 'views' => [ 224 | 'simple' => 'menus::simple.menu', 225 | 'bs-nav-stacked' => 'menus::bs-nav-stacked.menu', 226 | 'sbadmin2' => 'menus::sbadmin2.menu', 227 | 'adminto' => 'adminto::menus.sidebar.menu', 228 | 'admin-lte' => 'menus::admin-lte.menus', 229 | ] 230 | ``` 231 | 232 | Then you can customize `view.name` and receive `$menu` variable `Nurmanhabib\Navigator\NavCollection` 233 | 234 | ```html 235 | 269 | ``` 270 | 271 | 272 | ## Custom Renderer 273 | 274 | ```php 275 | use Nurmanhabib\LaravelMenu\Renders\NavViewRender; 276 | 277 | Menu::get('sidebar')->setRenderer(new NavViewRender('view.name')); 278 | ``` 279 | 280 | ------ 281 | 282 | ### API 283 | 284 | #### Nav 285 | 286 | ```php 287 | $nav->getText(); 288 | $nav->getUrl(); 289 | $nav->getIcon(); 290 | $nav->isActive(); 291 | $nav->isVisible(); 292 | $nav->hasChild(); 293 | $nav->getChild(); 294 | ``` 295 | 296 | 297 | 298 | #### NavCollection 299 | 300 | ```php 301 | $collection->addHeading(); 302 | $collection->addHome(); 303 | $collection->addSeparator(); 304 | $collection->addLink('Text', 'link', 'icon'); 305 | $collection->addParent('Text Parent', callback($child), 'icon', '#'); 306 | $collection->add($nav); 307 | $collection->getItems(); 308 | ``` 309 | 310 | ## Contributing 311 | 312 | I apologize if the documentation is still not perfect, if you are willing to contribute to the documentation please do a Pull Request. We also feel happy if we want to contribute to open source. 313 | --------------------------------------------------------------------------------