├── .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 |
2 | @foreach ($items as $item)
3 | @include('menus.admin-lte.menus-dropdown-item')
4 | @endforeach
5 |
6 |
--------------------------------------------------------------------------------
/resources/views/menus/sbadmin2/menu-2.blade.php:
--------------------------------------------------------------------------------
1 |
2 | @foreach ($menu->getItems() as $nav)
3 | @if ($nav->getType() == 'link')
4 | @include('menus::sbadmin2.item-2')
5 | @endif
6 | @endforeach
7 |
8 |
--------------------------------------------------------------------------------
/resources/views/menus/bs-nav-stacked/menu.blade.php:
--------------------------------------------------------------------------------
1 |
2 | @foreach ($menu->getItems() as $nav)
3 | @if ($nav->getType() == 'link')
4 | @include('menus::bs-nav-stacked.item')
5 | @endif
6 | @endforeach
7 |
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 | {{ $nav->getText() }}
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 |
2 | @foreach ($menu->getItems() as $nav)
3 | @if ($nav->getType() == 'heading')
4 | @include('menus::simple.heading', compact('nav'))
5 | @elseif ($nav->getType() == 'separator')
6 | @include('menus::simple.heading', compact('nav'))
7 | @else
8 | @include('menus::simple.item', compact('nav'))
9 | @endif
10 | @endforeach
11 |
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 |
20 | @if ($item->getData('method') == 'POST')
21 | @php($formId = uniqid('form-'))
22 |
27 |
28 |
29 | {{ $item->getText() }}
30 | @if ($badge = $item->getData('badge'))
31 | {{ Arr::get($badge, 'text') }}
32 | @endif
33 |
34 |
35 |
38 |
39 | @else
40 |
41 |
42 |
43 | {{ $item->getText() }}
44 | @if ($badge = $item->getData('badge'))
45 | {{ Arr::get($badge, 'text') }}
46 | @endif
47 |
48 |
49 | @endif
50 |
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 | 
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 |
236 | @foreach ($menu->getItems() as $item)
237 | @if ($item->getType() == 'heading')
238 | - {{ $item->getText() }}
239 | @elseif ($item->getType() == 'separator')
240 | - ---
241 | @else
242 | @if ($item->hasChild())
243 | -
244 |
245 | {{ $item->getText() }}
246 |
247 |
248 |
249 | @include('view.name', ['menu' => $item->getChild()])
250 |
251 | @else
252 | @if ($item->isActive())
253 | -
254 |
255 | {{ $item->getText() }}
256 |
257 |
258 | @else
259 | -
260 |
261 | {{ $item->getText() }}
262 |
263 |
264 | @endif
265 | @endif
266 | @endif
267 | @endforeach
268 |
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 |
--------------------------------------------------------------------------------