# Content

# Setup

Install package with composer:

composer require contributte/menu-control
1

Register as nette extension:

extensions:
	menu: Contributte\MenuControl\DI\MenuExtension

menu:
1
2
3
4

# Usage

You can write menu links as associated multi dimensional arrays. Because of this you are able to create any structure of menus and submenus you may need.

menu:
	front:
		items:
			Home:
				action: Front:Home:
			Books:
				link: '#'
				items:
					All:
						action: Front:Books:all
					Featured:
						action: Front:Books:featured
	admin:
		items:
			Users:
				action: Admin:Users:

			Books:
				action: Admin:Books:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php

namespace App;

use Contributte\MenuControl\UI\MenuComponentFactory;
use Contributte\MenuControl\UI\MenuComponent;
use Nette\Application\UI\Presenter;

final class BasePresenter extends Presenter
{

	/**
	 * @var MenuComponentFactory
	 */
	private $menuFactory;

	public function injectBasePresenter(MenuComponentFactory $menuFactory)
	{
		$this->menuFactory = $menuFactory;
	}

	protected function createComponentMenu(): MenuComponent
	{
		return $this->menuFactory->create('front');
	}

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
{control menu}              <!-- display menu -->
{control menu:breadcrumbs}  <!-- display breadcrumbs -->
{control menu:sitemap}      <!-- display sitemap -->
1
2
3

That structure in neon config will generate two menus:

front:

  • Home (action: Front:Home:)
  • Books (link: #)
    • All (action: Front:Books:all)
    • Featured (action: Front:Books:featured)

admin:

  • Users (action: Admin:Users:)
  • Books (action: Admin:Books:)

# Templates

This package includes 3 default templates (menu, breadcrumbs, sitemap). However only the default sitemap template should be used in real project. The other two templates should only help you in the beginning with building your own templates which will fit your's website look.

Changing templates can be done in your menu configuration:

menu:
	front:
		templates:
			menu: %appDir%/path/to/custom/menu.latte
			breadcrumbs: %appDir%/path/to/custom/breadcrumbs.latte
			sitemap: %appDir%/path/to/custom/sitemap.latte
1
2
3
4
5
6

As you can see, each menu can have different templates.

# Visibility of items

It may be useful to hide some links in specific situations. For that we have the visibility option on items where you can tell on which template the link should be visible.

menu:
	front:
		items:
			Home:
				action: Front:Home:
				visibility:
					menu: true
					breadcrumbs: false
					sitemap: true
1
2
3
4
5
6
7
8
9

# Mark active item via regex

Menu item can be labeled as active by a regular expression (or array of regular expressions) that is compared to the entire Presenter's name and action. You can set your regular expression via include setting.

menu:
	front:
		items:
			Home:
				action: Front:Home:
				include: '^Front\:Home\:[a-zA-Z\:]+$' # mark as active for all actions of "Front:Home:" presenter
			Books:
				action: Front:Books:
				include: # mark as active for actions "Front:Books:default" and "Front:Books:edit"
					- '^Front\:Books\:default$'
					- '^Front\:Books\:edit$'
1
2
3
4
5
6
7
8
9
10
11

# Translations

When displaying title of link in some template, we always work with translated titles.

You have three options for translator:

  • Do nothing: Original ReturnTranslator class will be used. This translator just returns the given text.
  • Set translator manually: Provide your own implementation of Nette\Localization\ITranslator.
  • Set translator to true: Menu extension will try to find your translator in DI container automatically.
services:
	- App\MyOwnFrontTranslator

menu:
	front:
		translator: @App\MyOwnFrontTranslator
	admin:
		translator: true
1
2
3
4
5
6
7
8

# Custom data

Every link can contain additional data which can be later used eg. in your custom latte templates.

menu:
	admin:
		items:
		
			Adminer:
				link: http://localhost:20000
				data:
					icon: fa fa-database
					attrs:
						target: _blank
1
2
3
4
5
6
7
8
9
10
<a href="{$item->getRealLink()" n:attr="(expand) $link->getData('attrs')">
	<i class="{$item->getData('icon')"></i> {$link->getRealTitle()}
</a>
1
2
3

# Authorization

Sometimes you may want to hide some links based on custom rules, that includes for example authorization from nette.

This menu package uses custom IAuthorizator interface which you can use to write your own authorizators.

<?php

namespace App;

use Contributte\MenuControl\IMenuItem;
use Contributte\MenuControl\Security\IAuthorizator;

final class FrontAuthorizator implements IAuthorizator
{
	
	public function isMenuItemAllowed(IMenuItem $item): bool
	{
		return isItemAllowed($item);
	}
	
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
services:
	- App\FrontAuthorizator

menu:
	front:
		authorizator: @App\FrontAuthorizator
1
2
3
4
5
6

When you want to display a link in your template it uses the ILinkGenerator interface to generate it from the data in your menu config. If you want to change the default logic (which uses link method from nette) you can just implement your custom link generator.

<?php

namespace App;

use Contributte\MenuControl\IMenuItem;
use Contributte\MenuControl\LinkGenerator\ILinkGenerator;

final class FrontLinkGenerator implements ILinkGenerator
{


	public function link(IMenuItem $item): string
	{
		return generateLink($item);
	}
	
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
services:
	- App\FrontLinkGenerator

menu:
	front:
		linkGenerator: @App\FrontLinkGenerator
1
2
3
4
5
6

You can also override link generator later for some subtree of links:

menu:
	front:
		items:
			Home:
				action: Front:Home:	
			Books:
				link: '#'
				linkGenerator: @App\BooksLinkGenerator
1
2
3
4
5
6
7
8

If you want to build your menu maybe from database instead of neon config, you can do that by creating IMenuLoader class.

See the default DefaultMenuLoader (opens new window) how it works.