> Markdown version of [Route Templates](https://vaadin.com/docs/v24/building-apps/views/pass-data/route-templates). Section index: [llms.txt](https://vaadin.com/docs/v24/building-apps/llms.txt)

# Route Templates Flow

In this guide, you’ll learn how to create a view that accepts multiple route parameters using route templates. You’ll also learn how to use modifiers and regular expressions to tweak the behavior of the route parameters. Finally, a mini-tutorial will help you apply these concepts in a real Vaadin application.

> **Tip:** Using a single [route parameter](https://vaadin.com/docs/v24/building-apps/views/pass-data/route-parameters/flow.md) is easier than using a route template. If you can get the job done using the `HasUrlParameter<T>` interface, use that instead.

## <a id="specifying-multiple-route-parameters"></a>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`:

```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"`

## <a id="accessing-route-parameter-values"></a>Accessing Route Parameter Values

To access the route parameter values, your view must implement the `BeforeEnterObserver` interface. This interface defines the `beforeEnter()` method, which is called by the router before navigating to the view. Inside the method, you can access the route parameters:

```java
@Route("customer/:customerId/:action")
public class CustomerView extends Main implements BeforeEnterObserver {

    private static final String PARAM_CUSTOMER_ID = "customerId"; // (1)
    private static final String PARAM_ACTION = "action";

    @Override
    public void beforeEnter(BeforeEnterEvent event) {
        var customerId = event.getRouteParameters().get(PARAM_CUSTOMER_ID).get();
        var action = event.getRouteParameters().get(PARAM_ACTION).get();
        // Process the parameters
    }
    ...
}
```

1. **Tip:** To improve readability and maintainability, declare route parameter names as constants near the `@Route` annotation.

The `RouteParameters` class defines methods for accessing route parameter values as `String`, `Integer`, or `Long`. They all return an `Optional<T>`.

In the example above, both `customerId` and `action` are required, so you can assume that those route parameter values are never empty. If you try to navigate to `/customer` or `/customer/cu12345`, the router returns a `404 Not Found` error.

## <a id="optional-route-parameters"></a>Optional Route Parameters

By default, all route parameters are required. To make a route parameter optional, use the `?` modifier:

```java
// tag::snippet[]
@Route("customer/:customerId/:action?") // (1)
// end::snippet[]
public class CustomerView extends Main implements BeforeEnterObserver {

    private static final String PARAM_CUSTOMER_ID = "customerId";
    private static final String PARAM_ACTION = "action";

    @Override
    public void beforeEnter(BeforeEnterEvent event) {
        var customerId = event.getRouteParameters().get(PARAM_CUSTOMER_ID).get();
// tag::snippet[]
        var action = event.getRouteParameters().get(PARAM_ACTION).orElse(null); // (2)
// end::snippet[]
        // Process the parameters
    }
    ...
}
```

1. The `action` route parameter is now optional.

2. The route parameter value can now be empty.

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 the `customer` route with no route parameters at all.

- `/customer/cu12345` → Calls the `customer` route with `"cu12345"` as the value of `customerId`.

- `/customer/cu12345/edit` → Calls the `customer` route with `"cu12345"` as the value of `customerId`, and `"edit"` as the value of `action`.

## <a id="wildcard-route-parameters"></a>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:

```java
@Route("api/:path*")
public class ApiViewer extends Main implements BeforeEnterObserver {

    @Override
    public void beforeEnter(BeforeEnterEvent event) {
        var path = event.getRouteParameters().get("path").orElse("");
        // Process the path
    }
}
```

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:

```java
@Route("api/:path*")
public class ApiViewer extends Main implements BeforeEnterObserver {

    @Override
    public void beforeEnter(BeforeEnterEvent event) {
// tag::snippet[]
        List<String> segments = event.getRouteParameters().getWildcard("path");
// end::snippet[]
        // Process the segments
    }
}
```

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.

## <a id="constraining-route-parameter-values-with-regular-expressions"></a>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 the `beforeEnter()` method.

> **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:

```java
// tag::snippet[]
@Route("customer/:customerId([0-9]{1,9})/:action?(view|edit)")
// end::snippet[]
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.

## <a id="try-it"></a>Try It

In this mini-tutorial, you’ll create a view that uses a route template. You’ll then change the route template and see how the view behaves.

Set Up the Project

First, generate a [walking skeleton with a Flow UI](https://vaadin.com/docs/v24/getting-started/start.md), [open](https://vaadin.com/docs/v24/getting-started/import.md) it in your IDE, and [run](https://vaadin.com/docs/v24/getting-started/run.md) it with hotswap enabled.

Create the View

Create a new package `[application package].tutorial.ui.view`. Then, in this package, create a new class called `TemplateView`:

TemplateView\.java

```java
import com.vaadin.flow.component.html.Main;
import com.vaadin.flow.router.BeforeEnterEvent;
import com.vaadin.flow.router.BeforeEnterObserver;
import com.vaadin.flow.router.Route;

@Route("template")
public class TemplateView extends Main implements BeforeEnterObserver {

    private static final String PARAM1 = "param1";
    private static final String PARAM2 = "param2";
    private static final String PARAM3 = "param3";

    @Override
    public void beforeEnter(BeforeEnterEvent event) {
        var param1 = event.getRouteParameters().get(PARAM1).orElse("N/A");
        var param2 = event.getRouteParameters().get(PARAM2).orElse("N/A");
        var param3 = event.getRouteParameters().get(PARAM3).orElse("N/A");
        setText("param1: \"" + param1 + "\", param2: \"" + param2
            + "\", param3: \"" + param3 + "\"");
    }
}
```

Open your browser and go to: <http://localhost:8080/template>

You should see:

```
param1: "N/A", param2: "N/A", param3: "N/A"
```

Define Required Route Parameters

Next, introduce the three route parameters, like this:

```java
// tag::snippet[]
@Route("template/:param1/:param2/:param3")
// end::snippet[]
public class TemplateView extends Main implements BeforeEnterObserver {
    ...
}
```

Now, go back to your browser. Because the route parameters are required and you haven’t provided any values, you should see a `Could not navigate to 'template'` error message.

To give values for the route parameters, navigate to this URL:

<http://localhost:8080/template/say/hello/vaadin>

You should see:

```
param1: "say", param2: "hello", param3: "vaadin"
```

Make Route Parameters Optional

You’re now going to make the first two route parameters optional. Add the `?` modifier to them:

```java
// tag::snippet[]
@Route("template/:param1?/:param2?/:param3")
// end::snippet[]
public class TemplateView extends Main implements BeforeEnterObserver {
    ...
}
```

Go back to your browser. You should still see all three route parameter values. However, watch what happens if you go to:

<http://localhost:8080/template/say>

Since the first two parameters are optional, the last parameter takes the first available value. You should see:

```
param1: "N/A", param2: "N/A", param3: "say"
```

Now add a second route parameter value by navigating to:

<http://localhost:8080/template/say/hello>

You should see:

```
param1: "say", param2: "N/A", param3: "hello"
```

Mark a Route Parameter as Wildcard

You’re now going to make the last route parameter a wildcard. Add the `*` modifier to it:

```java
// tag::snippet[]
@Route("template/:param1?/:param2?/:param3*")
// end::snippet[]
public class TemplateView extends Main implements BeforeEnterObserver {
    ...
}
```

Go back to the browser. If you reload the page, you should now see the following:

```
param1: "say", param2: "hello", param3: "N/A"
```

The `"hello"` string has moved from `param3` to `param2`. The reason for this is that wildcard route parameters are also optional. Next, navigate to the following URL:

<http://localhost:8080/template/say/hello/to/vaadin>

The last route parameter now holds two segments instead of one. You should see:

```
param1: "say", param2: "hello", param3: "to/vaadin"
```

Add Regular Expressions

You’re now going to add some regular expressions to constrain the route parameters. You’ll force `param1` to consist of digits only, and all the segments of `param3` to be one of `hello`, `to`, and `vaadin`:

```java
// tag::snippet[]
@Route("template/:param1?([0-9]*)/:param2?/:param3*(hello|to|vaadin)")
// end::snippet[]
public class TemplateView extends Main implements BeforeEnterObserver {
    ...
}
```

Go back to the browser. You should now see a `Could not navigate to 'template/say/hello/to/vaadin`. This is because the first route parameter value is not a number. To fix this, navigate to:

<http://localhost:8080/template/123/say/hello/to/vaadin>

You should see:

```
param1: "123", param2: "say", param3: "hello/to/vaadin"
```

Final Thoughts

You’ve now successfully implemented route templates in Flow. You learned how to:

- Specify multiple route parameters in a view.

- Make route parameters optional.

- Use a wildcard route parameter to capture multiple URL segments.

- Use regular expressions to constrain the values of route parameters.

You’re now ready to use route parameters in real Vaadin applications. Try specifying your own route template, and make a [custom API](https://vaadin.com/docs/v24/building-apps/views/navigate/flow.md#your-own-api) for navigating to it! Include at least one numeric route parameter, and use `RouteParameters.getInteger()` to retrieve it.
