> Markdown version of [Navigation using Navigator](https://vaadin.com/docs/next/tools/mpr/introduction/3-navigator). Section index: [llms.txt](https://vaadin.com/docs/next/tools/llms.txt)

# Navigator in Flow with MPR

This step is needed in case your Vaadin 7 or 8 application uses Navigator. If it isn’t the case, go back to the [framework selection](https://vaadin.com/docs/next/tools/mpr/introduction/3-legacy-uis.md).

The navigation with MPR can be done in three ways. You can choose the one most suitable for your application, but don’t mix them together. No other approach is supported at the moment.

The first way is to use the [Navigator together Flow’s Router](#mixed-navigation-and-routing). This is suitable for creating new views in Flow while maintaining the old views to be routed by the `Navigator`.

The second is using the [Navigator without mixing with Flow](#no-mixing). It’s suitable for projects with complex custom navigators.

Last, using only the [Flow’s Router](#no-navigator) is suitable for basic navigation setups that can be easily ported, or as the final stage of an incremental porting process.

> **Note:** Keep in mind that the old `Navigator` uses URLs with the "hash-bang" (`#!`) prefix. That prefix isn’t used by the Flow’s Router.

## <a id="mixed-navigation-and-routing"></a>Mixing Navigation & Flow Routing

It’s possible to use the legacy Navigator and Flow routing together.

Starting from the legacy application:

```java
public class NavigatorUI extends UI {
  @Override
  protected void init(VaadinRequest request) {
    CssLayout viewDisplay = new CssLayout();
    Navigator navigator = new Navigator(this, viewDisplay);

    navigator.addView("", HomeView.class);
    navigator.addView("away", AwayView.class);

    VerticalLayout content = new VerticalLayout(viewDisplay);
    setContent(content);
  }
}
```

You would make the `UI` into a Flow route by extending `MprNavigatorRoute`.

```java
@Route("")
public class MyNavigatorRoute extends MprNavigatorRoute {
    @Override
    public void configureNavigator(Navigator navigator) {
        navigator.addView("", HomeView.class);
        navigator.addView("away", AwayView.class);
    }
}
```

For a more complex example, you could have a `MainMenu` component that’s always visible and used to navigate between the views:

```java
public class MyNavigatorUI extends UI {
  @Override
  protected void init(VaadinRequest request) {
    CssLayout viewDisplay = new CssLayout();
    Navigator navigator = new Navigator(this, viewDisplay);

    navigator.addView("", HomeView.class);
    navigator.addView("away", AwayView.class);

    setContent(new VerticalLayout(new MainMenu(), viewDisplay));
  }
}

public class MainMenu extends HorizontalLayout {
    public MainMenu() {
        Button home = new Button("Home",
                event -> getUI().getNavigator().navigateTo(""));
        Button away = new Button("Away",
                event -> getUI().getNavigator().navigateTo("away"));

        addComponents(home, away);
    }
}
```

Here we can move the `MainMenu` to its own `RouterLayout` that’s used on all Routes that have it as the parent layout. All you need to do is create a Flow component (e.g., `MainLayout`) that contains the `MainMenu` component and add that to the `@Route` annotation.

```java
// Flow router target
@Route(value = "", layout = MainLayout.class)
public class MyNavigatorRoute extends MprNavigatorRoute {
    @Override
    public void configureNavigator(Navigator navigator) {
        navigator.addView("", HomeView.class);
        navigator.addView("away", AwayView.class);
    }
}

// Flow layout, used by the router
public class MainLayout extends VerticalLayout implements RouterLayout {
    public MainLayout() {
        add(new LegacyWrapper(new MainMenu()));
    }
}
```

This way you can make a single `MainLayout` that can be used both with the old navigator views, as well as with the new Flow views.

To add a Flow view we need to create the route target:

```java
@Route(value = "flow", layout = MainLayout.class)
public class FlowView extends Div {
}
```

Then add it to the `MainMenu` as a `Button`:

```java
public class MainMenu extends HorizontalLayout {
    public MainMenu() {
        Button home = new Button("Home",
                event -> getUI().getNavigator().navigateTo(""));
        Button away = new Button("Away",
                event -> getUI().getNavigator().navigateTo("away"));
        Button flow = new Button("Flow",
                event -> getUI().getNavigator().navigateTo("flow"));

        addComponents(home, away, flow);
    }
}
```

Now the menu can be used to navigate from a legacy view to a Flow view and back.

When requesting the `Navigator` to navigate to a view that isn’t registered in the `Navigator`, navigate to a corresponding Flow view, if available. Navigation from a Flow route to a legacy View also works through the `Navigator`.

By default the `MprNavigatorRoute` creates a `<div>` on the client-side, but this can be changed by annotating the subclass with `@Tag`.

`MainMenu`, `HomeView` and `AwayView` are legacy Vaadin 7 components and, `FlowView` and `MainLayout` are Flow components. `HomeView` and `AwayView` also implement `View`.

## <a id="no-mixing"></a>Use Navigator Without Flow Mixing

Navigator can be used as is by having a view display component that is wrapped in a `LegacyWrapper`.

Consider the following simple legacy navigator setup:

```java
public class MyUI extends UI {

    @Override
    protected void init(VaadinRequest request) {
        Navigator navigator = new Navigator(this, this);
        navigator.addView("", DefaultView.class);
        navigator.addView("subview", SubView.class);
    }
}
```

This would be changed to the following:

```java
@Route("")
public class Root extends Div {
    private final CssLayout content = new CssLayout();

    public Root() {
        add(new LegacyWrapper(content));

        Navigator navigator = new Navigator(UI.getCurrent(), content);
        navigator.addView("", DefaultView.class);
        navigator.addView("subview", SubView.class);
    }
}
```

Now, navigation to `localhost` would show `DefaultView` and `localhost#!subview` would show `SubView`, as is expected. The thing to note in this case is that Flow doesn’t receive any view change events.

## <a id="no-navigator"></a>Upgrading Views to Flow Routes

Another open path for navigator upgrade is to wrap the existing `View` classes into a `MprRouteAdapter<? extends View>` and give the adapter class a `Route`. Then the `navigator.addView("away", AwayView.class);` configuration in the previous example would be changed to:

```java
@Route(value = "away", layout = MainLayout.class)
public class AwayRoute extends MprRouteAdapter<AwayView> {
}
```

By default the `MprRouteAdapter` creates a `<div>` on the client-side, but this can be changed by annotating the subclass with `@Tag`.

Now, there is no need to setup a `Navigator` and the View still receives a `ViewChangeEvent` as it did with the navigator.

Any `ViewChangeListener` should be replaced with a `BeforeEnterListener` for the `beforeViewChange` and an `AfterNavigationListener` for the `afterViewChange` to the Flow UI. See [Navigation Lifecycle](https://vaadin.com/docs/next/flow/routing/lifecycle.md) documentation.

The next step is [Configuring UI Parameters](https://vaadin.com/docs/next/tools/mpr/introduction/4-ui-parameters.md).

`466CAFAE-0226-445A-9863-7665DAB99305`
