Docs

Documentation versions (currently viewingVaadin 24)

Router Layouts & Nested Router Targets

Explains router layouts and nested router targets.

All parent layouts of a navigation target component have to implement the RouterLayout interface. You can define a parent layout by adding the @Layout annotation to the class, or by using the optional element layout from the @Route annotation.

Automatic Layout Using @Layout

The value for the @Layout annotation path has to be unique for the project. Otherwise, the resolver won’t be able to determine which layout component should be used. Having multiple @Layout annotations with the same path throws an exception.

The example below renders all routes inside MainLayout:

@Layout
public class MainLayout extends Div
        implements RouterLayout {
}

@Route and @RouteAlias each contain an annotation attribute called, autoLayout. Setting that attribute to false will stop automatic layout; it will ignore any @Layout matching the route. Giving a class for the layout method in @Route also disables automatic layout and uses the one given.

@Route(autoLayout = false)
public class NoLayoutView extends Div {
}

@Route(layout = MyLayout.class)
public class DefinedLayoutView extends Div {
}

Defining a Layout in @Route

This next example renders CompanyComponent inside MainLayout by defining the layout for the route:

@Tag("div")
@Route(value = "company", layout = MainLayout.class)
public class CompanyComponent extends Component {
}

When using the @Route("path") annotation to define a route, the component renders by default in the <body> tag on the page when there is no @Layout for RouterLayout. This is because the element returned by HasElement.getElement() is attached to the <body> tag.

Layout Matching Routes

To configure which routes a @Layout annotated RouterLayout handles, the prefix of the route’s path can be given for the value.

The example below gives a value of /user, which would match the routes /user and /user/info:

@Layout(value="/user")

The default value is /, which matches all paths.

Multiple Router Target Components

Where multiple router target components use the same parent layout, the parent layout instances remain the same when the user navigates among the child components.

See Updating Page Title on Navigation for more information on this.

Multiple Parent Layouts

Use the @ParentLayout annotation to define a parent layout for components in the routing hierarchy. Where necessary, a parent can have its own parent layout.

In the example below, MainLayout is used for everything, which MenuBar is reused for views:

public class MainLayout extends Div
        implements RouterLayout {
}

@Layout
@ParentLayout(MainLayout.class)
public class MenuBar extends Div
        implements RouterLayout {
    public MenuBar() {
        addMenuElement(TutorialView.class, "Tutorial");
        addMenuElement(IconsView.class, "Icons");
    }
    private void addMenuElement(
            Class<? extends Component> navigationTarget,
            String name) {
        // implementation omitted
    }
}

@Route(value = "tutorial")
public class TutorialView extends Div {
}

@Route(value = "icons")
public class IconsView extends Div {
}

MainLayout encapsulates MenuBar, which in turn encapsulates TutorialView or IconsView — depending on where the user has navigated.

ParentLayout Route Control

Annotating a parent layout with @RoutePrefix("prefix_to_add") adds a prefix to its children’s route.

In the example here, PathComponent receives the some prefix from its parent, resulting in some/path as its final route:

@Route(value = "path", layout = SomeParent.class)
public class PathComponent extends Div {
    // Implementation omitted
}

@RoutePrefix("some")
public class SomeParent extends Div
        implements RouterLayout {
    // Implementation omitted
}

Absolute Routes

A child component can bypass the parent’s route prefix by adding absolute = true to its own @Route or @RoutePrefix annotations.

This generic example builds a MyContent class to add "something" to multiple places in the SomeParent layout, without adding the route prefix to the navigation path:

@Route(value = "content", layout = SomeParent.class,
       absolute = true)
public class MyContent extends Div {
    // Implementation omitted
}

Even though the full path would typically be some/content, the result is only content because it has been defined as "absolute".

The example here defines absolute = true in the middle of the chain:

@RoutePrefix(value = "framework", absolute = true)
@ParentLayout(SomeParent.class)
public class FrameworkSite extends Div
        implements RouterLayout {
    // Implementation omitted
}

@Route(value = "tutorial", layout = FrameworkSite.class)
public class Tutorials extends Div {
    // Implementation omitted
}

The bound route is framework/tutorial, although the full chain is some/framework/tutorial.

If a parent layout defines a @RoutePrefix, the "default" child could have its route defined as @Route("") and be mapped to the parent layout route. For example, Tutorials with route "" would be mapped as framework/.

7A96749F-CD19-4422-A2A2-B4ACD719C9FA