Navigating Views in Vaadin
So far in this tutorial series, you’ve built a Customer Relationship Management (CRM) application for listing and editing contacts. Now, you’ll add a dashboard view to the application. You’ll also add a responsive application layout, with a header and a navigation sidebar that can be toggled on small screens (see the screenshot here).
View Routes
You can make any Vaadin component a navigation target by adding an @Route("<path>")
annotation. Routes can be nested by defining the parent layout in the annotation: @Route(value = "list", layout=MainLayout.class)
.
Parent Layout
The application should have a shared parent layout with two child views. The first, MainLayout
: App Layout should have a header and navigation: ListView
: the default view, mapped to ""
; and DashboardView
: mapped to "dashboard"
. The second child should have a responsive application layout and navigation links.
Begin by creating a new Java class named MainLayout
in the views
package with the following content. This is the shared parent layout of both views in the application.
package com.example.application.views;
import com.example.application.views.list.ListView;
import com.vaadin.flow.component.applayout.AppLayout;
import com.vaadin.flow.component.applayout.DrawerToggle;
import com.vaadin.flow.component.html.H1;
import com.vaadin.flow.component.orderedlayout.FlexComponent;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.router.HighlightConditions;
import com.vaadin.flow.router.RouterLink;
import com.vaadin.flow.theme.lumo.LumoUtility;
public class MainLayout extends AppLayout { // (1)
public MainLayout() {
createHeader();
createDrawer();
}
private void createHeader() {
H1 logo = new H1("Vaadin CRM");
logo.addClassNames(
LumoUtility.FontSize.LARGE, // (2)
LumoUtility.Margin.MEDIUM);
var header = new HorizontalLayout(new DrawerToggle(), logo ); // (3)
header.setDefaultVerticalComponentAlignment(FlexComponent.Alignment.CENTER); // (4)
header.setWidthFull();
header.addClassNames(
LumoUtility.Padding.Vertical.NONE,
LumoUtility.Padding.Horizontal.MEDIUM);
addToNavbar(header); // (5)
}
private void createDrawer() {
addToDrawer(new VerticalLayout( // (6)
new RouterLink("List", ListView.class) // (7)
));
}
}
-
AppLayout
is a Vaadin layout with a header and a responsive drawer. -
Instead of styling the text with raw CSS, use Lumo Utility Classes shipped with the default theme.
-
DrawerToggle
is a menu button that toggles the visibility of the sidebar. -
Centers the components in the
header
along the vertical axis. -
Adds the
header
layout to the application layout’s nav bar, the section at the top of the screen. -
Wraps the router link in a
VerticalLayout
and adds it to theAppLayout
drawer. -
Creates a
RouterLink
with the text "List" andListView.class
as the destination view.
RouterLink automatically maintains the highlight
attribute currently active in the element, but there is no default styling for it. Add the following CSS to frontend/themes/flowcrmtutorial/styles.css
to highlight the selected link.
a[highlight] {
font-weight: bold;
text-decoration: underline;
}
Lastly, in ListView
, update the @Route
mapping to use the new MainLayout
like so:
@Route(value="", layout = MainLayout.class) // (1)
@PageTitle("Contacts | Vaadin CRM")
public class ListView extends VerticalLayout {
...
}
-
ListView
still matches the empty path, but now usesMainLayout
as its parent.
Now you’re ready to run the application. When you do, you should now see a header and a sidebar on the list view.
Dashboard View
Next, you’ll create a new dashboard view. It’ll show some basic statistics: the number of contacts in the system, and a pie chart of the number of contacts per company.
Now create a new Java class named DashboardView
in the views
package with the following content:
package com.example.application.views;
import com.example.application.services.CrmService;
import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.charts.Chart;
import com.vaadin.flow.component.charts.model.ChartType;
import com.vaadin.flow.component.charts.model.DataSeries;
import com.vaadin.flow.component.charts.model.DataSeriesItem;
import com.vaadin.flow.component.html.Span;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.router.PageTitle;
import com.vaadin.flow.router.Route;
import com.vaadin.flow.theme.lumo.LumoUtility;
@Route(value = "dashboard", layout = MainLayout.class) // (1)
@PageTitle("Dashboard | Vaadin CRM")
public class DashboardView extends VerticalLayout {
private final CrmService service;
public DashboardView(CrmService service) { // (2)
this.service = service;
addClassName("dashboard-view");
setDefaultHorizontalComponentAlignment(Alignment.CENTER); // (3)
add(getContactStats(), getCompaniesChart());
}
private Component getContactStats() {
Span stats = new Span(service.countContacts() + " contacts"); // (4)
stats.addClassNames(
LumoUtility.FontSize.XLARGE,
LumoUtility.Margin.Top.MEDIUM);
return stats;
}
private Chart getCompaniesChart() {
Chart chart = new Chart(ChartType.PIE);
DataSeries dataSeries = new DataSeries();
service.findAllCompanies().forEach(company ->
dataSeries.add(new DataSeriesItem(company.getName(), company.getEmployeeCount()))); // (5)
chart.getConfiguration().setSeries(dataSeries);
return chart;
}
}
-
DashboardView
is mapped to the"dashboard"
path and usesMainLayout
as a parent layout. -
Takes
CrmService
as a constructor parameter and saves it as a field. -
Centers the contents of the layout.
-
Calls the service to get the number of contacts.
-
Calls the service to get all companies, then creates a
DataSeriesItem
for each, containing the company name and employee count. Don’t worry about the compilation error, the missing method is added in the next step.
Note
|
Vaadin Charts is Commercial
Vaadin Charts is a collection of data visualization components that’s part of the Vaadin Pro subscription. Vaadin Charts comes with a free trial that you can activate in the browser. All Vaadin Pro tools and components are free for students through the GitHub Student Developer Pack. For an open source alternative for Vaadin Charts, check out the wide selection of community extensions via Vaadin Directory. |
Open Company.java
and add the following field and getter to get the employee count without having to fetch all of the entities.
@Formula("(select count(c.id) from Contact c where c.company_id = id)") // (1)
private int employeeCount;
public int getEmployeeCount(){
return employeeCount;
}
-
The Formula is a Hibernate feature that allows you to specify SQL snippets to fetch special fields. The query gets the count of employees without needing to fetch all of the employees. Note that in a larger application you’ll probably want to do this in some alternative way since all
Company
entity loads now triggers an additional SQL query, even though theemployeeCount
field is only needed in thisDashboardView
class.
Dashboard View in Main Layout Sidebar
To include a dashboard view in the main layout side base, add a navigation link to DashboardView
in the MainLayout
drawer:
private void createDrawer() {
addToDrawer(new VerticalLayout(
new RouterLink("List", ListView.class),
new RouterLink("Dashboard", DashboardView.class) // (1)
));
}
-
Add the Dashboard view to the drawer
Build and run the application again. You should now be able to navigate to the dashboard view and see stats on your CRM contacts. If you want, add or remove contacts in the list view to see that the dashboard reflects your changes.
On the next part of this tutorial, you’ll secure the application by adding a log-in screen.
52AFFD31-EA40-4AEF-B60F-E3BB6E5A8379