> Markdown version of [Navigating Between Routes](https://vaadin.com/docs/next/flow/routing/navigation). Section index: [llms.txt](https://vaadin.com/docs/next/flow/llms.txt)

# Navigating between Routes

Switching between routes or views can be initiated in two ways: programmatically using `UI.navigate()` methods; or by using links. The `navigate()` method is more agile for a Java programmer, as the view change can be issued from anywhere in your code and you can interact with the target view. Using links, however, is the native web way of moving from one view to another, allowing you for example to share the direct link to a specific view with a colleague, and they work even if the session has expired.

## <a id="server-side-navigation"></a>Server-Side Navigation

You can trigger navigation from the server-side code using various `UI.navigate()` methods.

You should primarily use `UI.navigate(Class<? extends Component> navigationTarget)` or `navigate(Class<? extends C> navigationTarget, RouteParameters parameters)` methods, where you pass the `Class` of the target view as a parameter. Compared to `String` versions, this avoids having to generate the route string manually.

In the browser, the `navigate()` method triggers a location update and the addition of a new history state entry, but doesn’t issue a full page reload.

**Example**: Navigation to the `UserEditor` view when clicking a button:

```java
Button button = new Button("Navigate to company");
button.addClickListener(e ->
     button.getUI().ifPresent(ui ->
           ui.navigate(UserEditor.class))
);
```

### <a id="interacting-directly-with-the-target-view"></a>Interacting directly with the Target View

The `navigate()` method where you give the target view class as a parameter returns the actual target view as `Optional`. This allows you to further configure the new view with its Java API.

The return value may be empty if the target view isn’t immediately available for some reason. This may happen, for example, because of security constraints or if the navigation was canceled or postponed in a [navigation lifecycle events](https://vaadin.com/docs/next/flow/routing/lifecycle.md).

**Example**: Creating an edit button that navigates to a separate view and assigns the DTO to the target view with its Java API:

```java
new Button("Edit " + user.getName(), event -> {
    ui.navigate(UserEditor.class)
            .ifPresent(editor -> editor.editUser(user));
})
```

With this code, Vaadin doesn’t have the data to maintain a deep link to edit the same entity. For the active user of the application, a view to edit the selected entity is opened, but they can’t share a direct link to edit the same entity with their colleague. If deep linking is required, the target view must [maintain enough details about the UI state in the URL](https://vaadin.com/docs/next/flow/routing/updating-url-parameters.md), or the developer must use route parameters to pass the data, instead of the direct Java API.

### <a id="passing-data-using-route-parameters"></a>Passing Data Using Route Parameters

If your target view implements `HasUrlParameter`, you can submit trivial data to the target view as route parameters. Compared to directly interacting with the target views Java API, this method automatically maintains the URL, which is beneficial for deep linking. However, you can’t pass more complex objects as route parameters as such, and you always need to consider data safety parameters that end up in URLs.

**Example**: Navigation to the `user/123` route target (where "123" is the parameter) upon clicking a button:

```java
Button editButton = new Button("Edit user details");
editButton.addClickListener(e ->
        editButton.getUI().ifPresent(ui -> ui.navigate(
                UserProfileEdit.class, "123"))
);
```

In addition to handling [Route Parameters](https://vaadin.com/docs/next/flow/routing/route-parameters.md) as in the above example, the `UI.navigate()` method has other overloads that allow you to pass [Query Parameters](https://vaadin.com/docs/next/flow/routing/additional-guides/query-parameters.md) or [Route Templates Parameters](https://vaadin.com/docs/next/flow/routing/additional-guides/route-templates.md) to the target view.

A location string may carry its query string and fragment itself, as in `ui.navigate("user/123?tab=orders#totals")`. The query string is parsed into the query parameters of the resulting location. Passing a `QueryParameters` object alongside such a location is an error — the parameters in the string would be lost — and throws an `IllegalArgumentException`. (since V25.3)

## <a id="using-the-routerlink-component"></a>Using the RouterLink Component

`RouterLink` is a special component based on the \<a> tag to create links pointing to route targets in your application.

Navigation with `RouterLink` fetches the content of the new component without reloading the page. The page is updated in place without a full page reload, but the URL in the browser is updated.

**Example**: Using `RouterLink` for a simple navigation target.

```java
void buildMenu() {
    menu.add(new RouterLink("Home", HomeView.class));
}

@Route(value = "")
public class HomeView extends Component {
}
```

**Example**: Using `RouterLink` for navigation targets with route parameters, where the navigation target class implements `HasUrlParameter`.

```java
void buildMenu() {
    menu.add(new RouterLink("Greeting",
            GreetingComponent.class, "default"));
}

@Route(value = "greet")
public class GreetingComponent extends Div
        implements HasUrlParameter<String> {

    @Override
    public void setParameter(BeforeEvent event,
            String parameter) {
        setText(String.format("Hello, %s!", parameter));
    }
}
```

**Example**: Using `RouterLink` for a navigation target with Route template route.

```java
void buildMenu() {
    // user/123/edit
    menu.add(new RouterLink("Edit user details",
            UserProfileEdit.class, new RouteParameters("userID", "123")));
    // user/edit
    menu.add(new RouterLink("Edit my details",
            UserProfileEdit.class));
}

@Route("user/:userID?/edit")
public class UserProfileEdit extends Div implements BeforeEnterObserver {

    private String userID;

    @Override
    public void beforeEnter(BeforeEnterEvent event) {
        userID = event.getRouteParameters().get("userID").
                orElse(CurrentUser.get().getUserID());
    }
}
```

> **Note:** Because the parameter is defined as optional, URL links are possible both with and without the parameter.

You can use `new RouterLink(viewClass)` if you want to embed other elements into `RouterLink` without text, for example images or icons.

**Example**: Using `RouterLink` with an icon instead of text.

```java
void buildMenu() {
    Icon vaadinIcon = new Icon(VaadinIcon.HOME);
    RouterLink link = new RouterLink(HomeView.class);
    link.add(vaadinIcon);
    menu.add(link);
}

@Route(value = "")
public class HomeView extends Component {
}
```

## <a id="using-standard-links"></a>Using Standard Links

It’s also possible to navigate with standard `<a href="company">` type links. You can do that via an `Anchor` component to which you would supply an `href` and `text` content:

```java
new Anchor("/hello", "Go to /hello route");
```

You can configure a standard link to open in a new tab by setting the anchor `target` attribute to `_blank`:

```java
Anchor anchor = new Anchor("/hello", "Go to /hello route");
anchor.getElement().setAttribute("target", "_blank");
```

Vaadin’s client-side router, which is based on [React Router](https://reactrouter.com/), intercepts all instances of anchor navigation, and clicking on a standard link doesn’t cause a full page reload to happen by default. If you want a full page reload to happen, for example when navigating to a page that isn’t implemented using Vaadin, you can add `router-ignore` [attribute](https://vaadin.com/docs/next/flow/component-internals/element-api/properties-attributes.md#about-attributes); for example, `<a router-ignore href="company">Go to the company page</a>`. This can be done from the Java API as follows:

```java
Anchor anchor = new Anchor("/hello", "Go to /hello route");
anchor.getElement().setAttribute("router-ignore", "");
```

## <a id="observing-navigation-state"></a>Observing Navigation State (since V25.2)

The `UI.routerStateSignal()` method returns a read-only signal that holds the current navigation state of the UI as a `RouterState`. The signal value is updated whenever a navigation completes, immediately before `AfterNavigationListener` implementations are notified, so reactive consumers and listeners observe the same state.

The signal lets reactive code — breadcrumbs, menus, or anything else that depends on the current location — track navigation without registering an `AfterNavigationListener` and manually fetching the initial state on attach:

```java
Signal<RouterState> routerState = UI.getCurrent().routerStateSignal();

Span currentPath = new Span();
currentPath.bindText(routerState.map(
        state -> "Current path: " + state.location().getPath()));
```

`RouterState` is an immutable record with the following components:

- `location()` — the `Location` of the current view, including the path, query parameters, and fragment.

- `routeParameters()` — the `RouteParameters` extracted from the URL.

- `activeChain()` — an unmodifiable list of the currently active route target and its parent layouts, leaf first.

- `navigationTarget()` — the class of the leaf route target.

The `currentView()` method returns the currently shown leaf view as an `Optional`.

Before the first navigation completes, the signal value is a `RouterState` with an empty `Location`, empty `RouteParameters`, an empty active chain, and a `null` navigation target.

Use `Signal.get()` to read the value reactively — inside a `Signal.effect()` this creates a dependency, so the effect runs again after each navigation — or `Signal.peek()` for a non-reactive snapshot. Fine-grained projections can be derived with `Signal.map()`, for example a signal holding only the location:

```java
Signal<Location> locationSignal = UI.getCurrent().routerStateSignal()
        .map(RouterState::location);
```

Combined with the [route hierarchy](https://vaadin.com/docs/next/flow/routing/route-hierarchy.md), the signal can drive a breadcrumb trail that updates on every navigation. See [Manage UI State with Signals](https://vaadin.com/docs/next/flow/ui-state.md) for more about signals and effects.

`3F7CDDD8-C4FB-44DC-9047-C48EAB57C862`
