Vaadin 10 is an almost complete rewrite of the successfull Vaadin framework and offers many new interesting and usefull features. One interesting feature is the router, that will superseed the navigator of Vaadin 8. With the @Route
annotation placed at the type definition of a view class, it is possible to use a template for this view class that will make layouting a Vaadin application nice and easy.
Layouting with Vaadin 10
To demonstrate the new templating feature of the @Route annotation, I created a small sample project that can be downloaded from https://bitbucket.org/mekasorocks/vaadin10starter
I wanted to create a Vaadin application with this layout:
The applicationlayout consists of
- a header on top of the page that contains
- a navigation on the left side of the header and
- some buttons to switch the language (localeswitch) of our application on the right
- a content area that will contain some form elements that are handled in view classes
- a sticky footer on the bottom of the page
Using the @Route
annotation
The @Route annotation for the default view (de.mekaso.vaadin.view.PersonView) of the project looks like
@Route(value = "", layout = ApplicationLayout.class)
The layout attribute must be a class that implements the com.vaadin.flow.router.RouterLayout
interface. Lets look at this class in the project.
Creating a RouterLayout
The ApplicationLayout
class is responsible for creating the layout for all our view classes:
@Theme(Lumo.class) @PageTitle("Vaadin10 Starter Project") @BodySize(height = "100vh", width = "100vw") @StyleSheet("applicationlayout.css") public class ApplicationLayout extends FlexLayout implements RouterLayout { ... @PostConstruct private void init() { // create the elements (header, content, footer) } }
The annotations for theme, page title and the page size and self explanatory. The @StyleSheet annotation will be used to style the flexbox layout I used for the application. The ApplicationLayout extends the Vaadin FlexLayout
class. The FlexLayout
is based on the Flexbox css module. With flexbox you can easily create responsive layouts with just few lines of code and some CSS stylings. It is a fast and professional way to layout your application. Documentation and tricks about flexbox can be found at CSS Tricks or W3Schools.
Create some layout elements
The init method of the ApplicationLayout
class is automatically called by the CDI container by using the @PostConstruct
annotation. Here the layout elements for header, content and footer are created and added to the FlexLayout container (lines 30 – 32). As you can see I gave the FlexLayout
container an ID (“applicationlayout”) and added style classes to the elements of the layout. I used the ID and style classes to style and layout the elements in the stylesheet file applicationlayout.css.
@PostConstruct private void init() { super.setId("applicationlayout"); // navigation Div navigation = createNavigation(); navigation.addClassName("navigation"); // locale switch Div localeButtons = new Div(); localeButtons.addClassName("localeswitch"); for (Locale locale : this.i18nProvider.getProvidedLocales()) { Button localeButton = new Button(locale.getLanguage()); localeButton.addClickListener(click -> { if (this.getUI().isPresent()) { this.getUI().get().setLocale(locale); this.localeChanger.fire(new LocaleChangeEvent(this.getUI().get(), locale)); } }); localeButtons.add(localeButton); } // header with navigation and locale switch this.header = new Div(navigation, localeButtons); this.header.addClassName("header"); // the content this.contentContainer = new Div(); this.contentContainer.addClassName("content"); // sticky footer this.footer = new Div(); this.footer.addClassName("footer"); this.footer.add(new Text("Vaadin 10 Starterproject 2018")); add(this.header); add(this.contentContainer); add(this.footer); }
Now all elements (except the actual content) are created and added to the application layout. We can already see the elements when calling the application in a web browser. However we need to tell the application layout class to add the content area to our layout and add the elements of the view classes to the content area when the view classes are called.
Populating the content area
The RouterLayout
interface offers showRouterLayoutContent(HasElement content)
method, that we need to override in order to place the content elements to our layout:
@Override public void showRouterLayoutContent(HasElement content) { if (content != null) { this.contentContainer.removeAll(); this.contentContainer.add(Objects.requireNonNull((Component)content)); } }
Without overriding the method the content elements of the view classes would be added after all other layout elements (at the bottom of the page). We just needed to remove all elements from the content container and add the content element to this container.
Styling the FlexLayout
Finally we need some lines of CSS to have a proper layout that will place the header on top, the content area in the middle and the footer on the bottom of the page:
#applicationlayout { display: flex; min-height: 100vh; flex-direction: column; } #applicationlayout .header { padding: 10px; } #applicationlayout .content { flex: 1; padding: 10px; } #applicationlayout .navigation { float: left; } #applicationlayout .navigation vaadin-button { margin-right: 10px; } #applicationlayout .localeswitch { float: right; } #applicationlayout .localeswitch vaadin-button { margin-left: 10px; } #applicationlayout .footer { border-top: 1px dashed; text-align: center; padding: 10px; }
Here you can see that I initialized the applicationlayout container with a flex layout (lines 1-5). The content area should use all remaining vertical space (lines 9-12) and the footer should remain on the bottom of the page with 10 pixel padding to the content. The result will look like that:
By using the features of RouterLayout
you can create Vaadin 10 applications with a flexible layout for all your view classes. This whole concept of templating is very similar to the (old-school) templating framework Tiles. I always liked the concepts of tiles as it was simple and straight to the point. Using this approach in Vaadin is a major progress and a cool new feature of this UI framework.