Route Templates
- Copy-Paste into Your Project
- Specifying Multiple Route Parameters
- Accessing Route Parameter Values
- Optional Route Parameters
- Wildcard Route Parameters
- Constraining Route Parameter Values with Regular Expressions
In this guide, you’ll learn how to create a view that accepts multiple route parameters using route templates, and how to read those parameters reactively with a signal. You’ll also learn how to use modifiers and regular expressions to tweak the behavior of the route parameters.
Using a single route parameter is easier than using a route template. If you can get the job done using the HasUrlParameter<T> interface, use that instead.
Copy-Paste into Your Project
If you want to quickly try out route templates in your Vaadin application, copy-paste the following code into a new Java class named RouteTemplateView in your project’s main package:
Source code
RouteTemplateView.java
This view reads its route parameters from the router state signal and binds a Paragraph to each, so the displayed values update automatically whenever the URL changes. For more detailed instructions on how to use route templates, continue reading below.
Specifying Multiple Route Parameters
To specify multiple route parameters, you use a route template instead of a static path when declaring a @Route. In a route template, one or more of the URL segments is a route parameter. Route parameters must follow the following syntax:
:parameter_name[modifier][(regex)]
The following sections explain this syntax in detail.
The following example demonstrates a view with two route parameters: customerId and action:
Source code
Java
@Route("customer/:customerId/:action")
public class CustomerView extends Main {
...
}Now, if you navigate to /customer/cu12345/edit, the router renders the CustomerView with the following route parameter values:
-
customerId→"cu12345" -
action→"edit"
Accessing Route Parameter Values
The current route parameters are available as a signal. Calling UI.getCurrentOrThrow().routerStateSignal() returns a read-only signal whose value is a RouterState record; its routeParameters() method gives you the RouteParameters for the active navigation.
A convenient pattern is to derive a separate signal for each parameter. Because Signal is a functional interface, you can define one with a lambda that reads the value from the router state:
Source code
Java
private static final String PARAM_ID = "id"; 1
private static final String PARAM_ACTION = "action";
private final Signal<String> idParam = () -> UI.getCurrentOrThrow()
.routerStateSignal().get().routeParameters().get(PARAM_ID)
.orElse(null);-
Tip: To improve readability and maintainability, declare route parameter names as constants near the
@Routeannotation.
Bind components to these parameter signals as you would to any other signal — for example, with bindText():
Source code
Java
idParagraph.bindText(() -> "ID: " + idParam.get());The value is read inside the binding’s reactive context, so the paragraph re-renders automatically whenever the parameter changes — including when the view navigates to itself with new values. The RouteParameters class defines methods for reading values as String, Integer, or Long; they all return an Optional<T>. The sections below show just the relevant accessor call on routeParameters — that is, the body of each parameter signal’s lambda.
|
Important
|
Read each parameter defensively, supplying a default with orElse() rather than orElseThrow(). A binding is first evaluated while the view is being constructed — before the router has populated the state with the navigation’s parameters — so even a required parameter is briefly absent. Returning a default keeps that first evaluation harmless, and the binding re-runs with the real value once navigation completes. (A missing required parameter in the URL itself still yields a 404 Not Found: navigating to /customer when the route requires more segments simply fails to match.)
|
|
Note
|
The router state signal is read-only. To change the parameters, navigate to the view with new values, as the showView() method in the copy-paste example does. If you need to inspect parameters imperatively — for example, to redirect before the view renders — implement BeforeEnterObserver and read event.getRouteParameters() inside beforeEnter().
|
Optional Route Parameters
By default, all route parameters are required. To make a route parameter optional, use the ? modifier:
Source code
Java
@Route("customer/:customerId/:action?") 1-
The
actionroute parameter is now optional.
The route parameter value can now be empty, so read it with a default:
Source code
Java
routeParameters.get(PARAM_ACTION).orElse(null)Now, if you navigate to /customer/cu12345, the action route parameter is empty. You can handle empty parameters by providing a default value, redirecting users, or displaying an error message.
When using multiple optional route parameters, values are assigned from left to right. If a parameter is missing, the next available value shifts left to fill its place. For instance, consider an application with the route customer/:customerId?/:action?:
-
/customer→ Calls thecustomerroute with no route parameters at all. -
/customer/cu12345→ Calls thecustomerroute with"cu12345"as the value ofcustomerId. -
/customer/cu12345/edit→ Calls thecustomerroute with"cu12345"as the value ofcustomerId, and"edit"as the value ofaction.
Wildcard Route Parameters
By default, a route parameter captures only a single URL segment. However, the last segment in the route template can be declared a wildcard route parameter. This means that the route parameter captures all the segments in its place. A wildcard route parameter is always optional.
To denote a route parameter a wildcard, use the * modifier:
Source code
Java
@Route("api/:path*")Read the captured path as a single string:
Source code
Java
routeParameters.get("path").orElse("")Now, if you navigate to api/com/vaadin/flow/, the path route parameter has the value "com/vaadin/flow".
You can also access the URL segments captured by a wildcard route parameter individually with getWildcard():
Source code
Java
routeParameters.getWildcard("path")Now, if you navigate to the same URL, the segments variable contains the list ["com", "vaadin", "flow"].
|
Note
|
If a route parameter is missing, getWildcard() returns an empty list.
|
Constraining Route Parameter Values with Regular Expressions
In all the examples discussed, the route parameters accept any value. However, a specific value is often expected for a route parameter and the view should be shown only when that specific value is present in the URL. You can do this by defining a regular expression for the route parameter. This reduces the need for validation and sanitation of route parameter values in your view.
|
Note
| The syntax of the regular expressions is checked at application startup. If there is an error, the application fails to start. |
In the following example, the customerId route parameter is constrained to an integer between 1 and 9 digits, and the action route parameter can be either "view", "edit", or empty:
Source code
Java
@Route("customer/:customerId([0-9]{1,9})/:action?(view|edit)")
public class CustomerView extends Main {
...
}If you navigate to a URL that doesn’t meet these constraints, you’ll receive a 404 Not Found error.
When you specify constraints on wildcard route parameters, the regular expression is applied to every segment that would be captured by the route parameter. If any of the segments fails to match the expression, the whole route template fails to match the URL, and you’ll get a 404 Not Found error.