Docs

Route Parameters

Learn how to use route parameters in Vaadin.

In this guide, you’ll learn how to create a view that accepts a single route parameter, holds it in a signal so the UI updates reactively, and keeps the browser URL in sync. You’ll also explore the differences between optional and wildcard route parameters.

Copy-Paste into Your Project

If you want to quickly try out route parameters in your Vaadin application, copy-paste the following code into a new Java class named RouteParameterView in your project’s main package:

Source code
RouteParameterView.java

This view stores the route parameter in a signal, binds its text to a value derived from that signal, and updates the URL whenever the signal changes. For more detailed instructions on how to use route parameters, continue reading below.

What Are Route Parameters?

Route parameters are dynamic segments in a URL that allow extra information to be passed to a view. They are appended to the route path and can be used to personalize responses or modify application behavior.

For example, if an application has a greet route that accepts a string parameter, users can call it with URLs like:

  • /greet/John

  • /greet/Jane

  • /greet/World

Here, "John", "Jane", and "World" are parameter values that the greet route can use to generate a response.

Route Parameters vs Static Routes

Static routes always take precedence over dynamic ones. For instance, consider an application with both a customer route (which accepts a string parameter), and a customer/list route:

  • /customer/cu1234 → Calls the customer route with "cu1234" as the parameter value.

  • /customer/details → Calls the customer route with "details" as the parameter value.

  • /customer/list → Calls the dedicated customer/list route.

  • /customer → Returns a 404 Not Found error, unless the parameter is explicitly declared optional.

Accessing the Route Parameter Value

To pass a route parameter to a Vaadin view, implement the HasUrlParameter<T> interface. This interface requires a type argument, which can be Long, Integer, String, or Boolean. It defines the setParameter() method, which receives the route parameter when the view is navigated to.

For example, to create a CustomerView that takes a customer ID as a parameter, use the following code:

Source code
Java
@Route("customers")
public class CustomerView extends Main implements HasUrlParameter<String> {

    @Override
    public void setParameter(BeforeEvent event, String parameter) {
        setText("Customer ID: " + parameter);
    }
}

Now, if you navigate to /customers/cu12345, the router calls setParameter() with "cu12345" as the parameter value.

Optional Parameters

By default, route parameters are required. In the example above, if you try to navigate to /customers, the router returns a 404 Not Found error.

To make a route parameter optional, add the @OptionalParameter annotation:

Source code
Java
@Route("customers")
public class CustomerView extends Main implements HasUrlParameter<String> {

    @Override
    public void setParameter(BeforeEvent event, @OptionalParameter String parameter) {
        if (parameter == null) {
            showCustomerList();
        } else {
            showCustomerWithId(parameter);
        }
    }

    private void showCustomerList() {
        // ...
    }

    private void showCustomerWithId(String customerId) {
        // ...
    }
}

Now, if you now navigate to /customers, the router calls setParameter() with null as the parameter value.

Wildcard Parameters

By default, a route parameter captures only a single URL segment. For example, if your customers route expects a string parameter, navigating to /customers/cu1234/edit would result in a 404 Not Found error.

To capture multiple URL segments as a single parameter, use the @WildcardParameter annotation:

Source code
Java
@Route("customers")
public class CustomerView extends Main implements HasUrlParameter<String> {

    @Override
    public void setParameter(BeforeEvent event, @WildcardParameter String parameter) {
        if (parameter.isEmpty()) {
            showCustomerList();
        } else {
            // Extract the and process the segments from the parameter
        }
    }

    private void showCustomerList() {
        // ...
    }
}

Now, navigating to /customers/cu1234/edit passes "cu1234/edit" as the parameter value.

Note
An empty wildcard parameter is an empty string (""), while an empty optional parameter is null. So, navigating to /customers calls setParameter() with "" instead of null.

If you’re considering wildcard parameters because you need multiple route parameters, Route Templates may be a better solution.

Holding the Parameter in a Signal

The CustomerView examples above set text directly inside setParameter(). That works for trivial views, but as soon as several parts of the UI depend on the parameter, you have to remember to update each of them by hand every time the value changes.

A cleaner approach — the one used by the copy-paste example at the top of this guide — is to store the parameter in a signal and let the UI derive from it. The signal becomes the single source of truth: setParameter() only writes the incoming value to the signal, and every component that depends on the parameter binds to it and updates itself automatically.

Source code
Java
private final ValueSignal<String> parameter = new ValueSignal<>(null);

@Override
public void setParameter(BeforeEvent event, @OptionalParameter String parameterValue) {
    parameter.set(parameterValue);
}

The parameter is held in a ValueSignal<String>, initialized to null for the "no value" case. When the router calls setParameter(), it writes the incoming value — which may be null for an optional parameter — straight to the signal.

Components don’t read the parameter directly. Instead, they bind to the signal and re-render whenever it changes. The copy-paste example binds a Paragraph with bindText():

Source code
Java
parameterValue.bindText(() -> Optional.ofNullable(parameter.get())
        .map(value -> "Parameter value: " + value)
        .orElse("No parameter value provided"));

Anything else that depends on the parameter — an enabled state, a visible flag, a nested component — can bind to the same signal in the same way. See Component Bindings for the full set of binding methods.

Keeping the URL in Sync

Because the signal is the source of truth, the URL should follow it: when the value changes, the browser’s address bar should update to match. A signal effect handles this. Reading parameter.get() inside the effect makes it re-run whenever the value changes, navigating the view to itself with the current parameter:

Source code
Java
Signal.effect(this,
        () -> UI.getCurrent().navigate(RouteParameterView.class,
                parameter.get()));

The effect is bound to the view’s lifecycle, so it’s active only while the view is attached. Navigating the view to itself reuses the existing instance and updates the URL; because the target location matches the current one whenever setParameter() was the source of the change, this doesn’t cause a navigation loop.

Updated