You are browsing the unmaintained documentation for old Nette 2.0. See documentation for current Nette.

Creating URL Links

Creation of links belongs to the strongest features of Nette Framework. Thanks to two-way routing you don't have to hardcode your URLs or nastily assemble them. You can just refer to actions of presenters, and pass them parameters and the framework will generate URLs by itself. Creating links is as easy as calling a function. You will really like it!

When programming and coding templates, we don't have to care about URLs design, we will refer directly to action of presenter, that's for example the already mentioned Product:show.

Most often we create links in templates. To make it as easy as possible the framework offers three macros. The smartest of them is n:href

<a n:href="Product:show $productId">product detail</a>

Note, that instead of the HTML attribute href we've used n:macro n:href. Its value isn't a URL, as you are used to with the href attribute, but directly an action of a presenter. The syntax is

[Presenter:]action [,] [arg1] [, arg2] [, ...]

After clicking on the link, method ProductPresenter::renderShow() will get its word and as parameter $id will get the value of $productId. We can pass even more parameters in the same way, just like we call a method. Could it get any easier?

Best practise is to write the presenter with a capital letter and the action without. The separator is a colon.

Besides that, it's even possible to pass named parameters. The next link passes the parameter lang with value cs:

<a n:href="Product:show $productId, lang => cs">product detail</a>

Although the method renderShow doesn't have $lang in its declaration, it can read the value of this parameter by calling $lang = $this->getParameter('lang').

If we have all parameters in an array, we can expand them with (expand) operator:

{var $args = [$productId, lang => cs]}
<a n:href="Product:show (expand) $args">product detail</a>

If the template, in which we are creating links, is part of the Product presenter, we can omit the name of the presenter and write directly n:href="show $productId". Similarly, if a link leads to the an action named default, you can skip that and write n:href="Product: $id" (don't forget the colon).

Links can even refer to other modules. Here we distinguish, if it's referring “relatively” to a submodule, or “absolutely” to a different module – then the path begins with a colon. Let's assume that the actual presenter is part of module Front, then we will write:

<a n:href="Shop:Product:show">link for Front:Shop:Product:show</a>
<a n:href=":Admin:Product:show">link for Admin:Product:show</a>

A special case is linking to itself. Here we'll write this as the target.

The generated link is in absolute path format. When you want to generate an absolute link including the domain, for example http://example.com, simply supply two slashes at the beginning n:href="//show $productId". If we set the property $absoluteUrls in presenter to TRUE, all the links will be absolute by default.

We can refer to specific parts on the page using so called fragments, or anchors, with the hash # symbol:

<a n:href="show#comments">link to Product:show and fragment #comments</a>

The macro n:href is really handy if we are creating an HTML tag <a>. When we want to have this link elsewhere, for example in the text of the template, we can use the {link} macro with the same internal syntax:

The address is: {link Product:show $productId}

{ifCurrent $link}...{/ifCurrent} is a conditional statement. If the link is referring to the current page, the block inside the tags is executed; otherwise it is discarded. Typical use case is adding CSS classes to the active link.

<!-- use cases -->
<a href="{link edit, 10}">edit</a>
<ul class="menu">
	<li><a href="{link Default:default}">...</a></li>
	<li><a href="{link}">...</a></li>
	...
	<li {ifCurrent Default:default}class="active"{/ifCurrent}><a href="{link Default:default}">...</a></li>

	<!-- scope expanding -->
	<li {ifCurrent Default:*}class="active"{/ifCurrent}><a href="{link Default:default}">...</a></li>
</ul>
<!-- negation -->
{ifCurrent Admin:login}{else}<a href="{link Admin:login}">Sign in!</a>{/ifCurrent}

Read more details about the syntax of Latte templates.

Linking in presenter

Presenter and a component have the method link, which can be used to create links just like in a template. The first argument is presenters target action, followed by passed arguments:

$url = $this->link(destination [,arg [,arg ...]]);

They can also be passed using an array. Examples:

$url = $this->link('Product:show', $productId);

$url = $this->link('Product:show', array($productId, 'lang' => 'en'));

If you pass FALSE as method parameter when generating a link, it won't be added to the link at all. The solution is to define this parameter with default value TRUE or FALSE. Nette will then understand that its type is boolean, and it will be passed to the url as 1 or 0, and converted back to boolean when processed by a presenter.

It may happen that we create an invalid link – either because it refers to a non-existing presenter, or because it passes more parameters that the target method receives in its definition, or when there can't be a generated URL for the targeted action. What to do with invalid links is determined by the static variable Presenter::$invalidLinkMode. It can have one of these values (constants):

  • Presenter::INVALID_LINK_SILENT – silent mode, returns symbol # as URL
  • Presenter::INVALID_LINK_WARNING – visual warning
  • Presenter::INVALID_LINK_EXCEPTION – there will be thrown an exception InvalidLinkException

Default setup in production mode is INVALID_LINK_SILENT and in development mode it's INVALID_LINK_WARNING. When setup to INVALID_LINK_WARNING, presenter and components returns error message as URL which stars with error:. To make such links visible, we will add CSS rule to our stylesheet:

a[href^="error:"] {
	background: red;
	color: white;
}