Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions articles/components/tabs/index.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,23 @@ include::{root}/frontend/demo/component/tabs/react/tabs-content.tsx[render,tags=
endif::[]
--

ifdef::flow[]
=== Navigating Between Views (Flow)

Tabs can also navigate between views, for example to switch between the sub-views of a settings page. Put the tabs in a <</flow/routing/layout#,router layout>>, and add a [classname]`RouterLink` to each tab. Clicking a tab then navigates to its view, and users can open the view in a new browser tab, or bookmark it.

Navigation can also happen without clicking a tab, for example when the user opens a link or uses the browser's back button. To keep the selected tab in sync with the view being shown, select the tab after each navigation in the layout's [methodname]`afterNavigation()` method. Disable autoselect, so that no tab is selected when the view being shown doesn't have a tab.

[source,java]
----
include::{root}/src/main/java/com/vaadin/demo/component/tabs/routes/SettingsLayout.java[tags=snippet,indent=0]
----

Each view uses the layout through the `layout` attribute of its `@Route` annotation, for example `@Route(value = "settings/profile", layout = SettingsLayout.class)`.

For the main navigation of an application, use <<../side-nav#,Side Navigation>> instead. It highlights the item of the current view automatically.
endif::[]

=== Lazy Initialization of Tab Contents

Sometimes it can be desirable to initialize the contents for a tab, lazily. That is to say, delay its initialization until the tab is selected. When you first click on one of the tabs below, you'll notice a loading indicator, and a short delay until the tab content is displayed for each.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.vaadin.demo.component.tabs.routes;

import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.router.Route;

@Route(value = "component/tabs/settings/notifications", layout = SettingsLayout.class)
public class NotificationsView extends VerticalLayout {

public NotificationsView() {
add("Notifications settings");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.vaadin.demo.component.tabs.routes;

import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.router.Route;

@Route(value = "component/tabs/settings/profile", layout = SettingsLayout.class)
public class ProfileView extends VerticalLayout {

public ProfileView() {
add("Profile settings");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package com.vaadin.demo.component.tabs.routes;

import java.util.HashMap;
import java.util.Map;

import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.component.tabs.Tab;
import com.vaadin.flow.component.tabs.Tabs;
import com.vaadin.flow.router.AfterNavigationEvent;
import com.vaadin.flow.router.AfterNavigationObserver;
import com.vaadin.flow.router.RouterLayout;
import com.vaadin.flow.router.RouterLink;

// tag::snippet[]
public class SettingsLayout extends VerticalLayout
implements RouterLayout, AfterNavigationObserver {

private final Tabs tabs = new Tabs();
private final Map<Class<? extends Component>, Tab> tabsByView = new HashMap<>();

public SettingsLayout() {
tabs.setAutoselect(false);
addTab("Profile", ProfileView.class);
addTab("Notifications", NotificationsView.class);
add(tabs);
}

private void addTab(String text, Class<? extends Component> view) {
Tab tab = new Tab(new RouterLink(text, view));
tabsByView.put(view, tab);
tabs.add(tab);
}

@Override
public void afterNavigation(AfterNavigationEvent event) {
// The first element of the active chain is the view being shown
Class<?> view = event.getActiveChain().getFirst().getClass();
tabs.setSelectedTab(tabsByView.get(view));
}
}
// end::snippet[]
Loading