public class PlaygroundAppLayout extends ApplicationLayout {
private static final long serialVersionUID = -5604950024464910529L;
public PlaygroundAppLayout() {
super(new PlaygroundApplicationConfig());
}
}
Application Framework
ApplicationLayout
When using linkki Application Framework, all views should be displayed in a customized ApplicationLayout
which provides the application frame. Therefore, the first step to use application framework is to create a subclass of ApplicationLayout
.
The main purpose of this class is to hold the custom implementation of ApplicationConfig in which the application frame is configured. This custom implementation can be passed to the super constructor. The implementation of ApplicationLayout
itself should have a default constructor which makes it usable as a RouterLayout.
The ApplicationLayout
surrounds the view with an ApplicationHeader
and an optional ApplicationFooter
.
The header is designed to have multiple menu actions on the left and may have some specific items like help menu or preferences on the right side.
The footer is hidden by default and can simply contain some application info.
Between ApplicationHeader
and ApplicationFooter
is the main area that displays the current view.
Application Configuration
The main aspects of the application are configured using the ApplicationConfig
. This interface needs to be implemented once in every linkki application and provided to the ApplicationLayout
.
ApplicationInfo
ApplicationConfig
refers to an ApplicationInfo
, which defines basic information about the application, such as name and copyright. Furthermore, parts of an ApplicationLayout
are configured by the ApplicationConfig
, such as the header, footer, as well as converters that should be used to convert values between UI and the underlying model.
Application Header
ApplicationConfig#getApplicationHeader
configures the application header. An ApplicationHeader
consists of two menu bars: one on the left, and one on the right.
The menu actions on the left are directly defined in the Application Configuration by the method getMenuItemDefinitions.
The menu bar on the right contains a help menu by default. In the help menu, a sub menu item displays the ApplicationInfo in a dialog. The right menu can be customized as follows:
-
Create a custom subclass of
ApplicationHeader
-
In the subclass:
-
To customize items of the help menu, override
addHelpMenuItems
-
To add submenu items for toggling between different theme variants, use
addThemeVariantToggles(MenuItem, ThemeVariantToggleMenuItemDefinition…)
-
-
To customize items of the menu bar, override
createRightMenuBar
-
-
Use the custom subclass in
ApplicationConfig#getHeaderDefinition
The right menu and its items have the following IDs by default:
As HTML IDs are very convenient for UI testing, custom items added to the menu should also set an ID. |
The class ApplicationMenuItemDefinition can be used to create items for the right menu. |
ThemeVariantToggleMenuItemDefinition
MenuItems
for theme variants can be added using the method addThemeVariantToggles(MenuItem, ThemeVariantToggleMenuItemDefinition…)
for example by overriding ApplicationHeader#createRightMenuBar
.
@Override
protected MenuBar createRightMenuBar() {
MenuBar rightMenuBar = super.createRightMenuBar();
MenuItem settings = rightMenuBar.addItem(VaadinIcon.COG.create());
settings.setId("appmenu-settings");
addThemeVariantToggles(settings, ThemeVariantToggleMenuItemDefinition.LUMO_DARK,
ThemeVariantToggleMenuItemDefinition.LINKKI_CARD,
ThemeVariantToggleMenuItemDefinition.LINKKI_COMPACT);
return rightMenuBar;
}
ApplicationMenuItemDefinition
MenuItems
can be added to the ApplicationHeader
using ApplicationMenuItemDefinition
.
For creation, ApplicationMenuItemDefinition
provides following constructors:
-
ApplicationMenuItemDefinition(String, String, Handler)
: Name and ID of the menu and aHandler
that is executed on click. -
ApplicationMenuItemDefinition(String, String, List<ApplicationMenuItemDefinition>)
: Name and ID of the menu and a list ofApplicationMenuItemDefinitions
as sub-menu items. Sub-menus are added in order as defined in the sub-menu list. -
ApplicationMenuItemDefinition(String, String, String)
: Name and ID of the menu and a URL as String to navigate to on click. This method handles both external and internal links. -
ApplicationMenuItemDefinition(String, String, Class<? extends Component>)
: Name and ID of the menu and aClass
to navigate to. The given class should be a route component.
More complex menu items can be implemented by creating menu item definitions directly instead of inheriting. If the implementation needs to be customizable, it can be easily done by composing ApplicationMenuItems
.
The following example uses a factory class to create the menu. A menu item contains one sub-menu item with caption "New". If only one sub-sub-menu item is given, the sub-menu-item shows a notification on click (caption → New). If multiple sub-sub-menu items are given, those are shown in the sub-menu item (caption → New → sub-sub-menu items). This can be used in ApplicationConfig#getMenuItemDefinitions()
public class CustomMenuItemDefinitionCreator {
private CustomMenuItemDefinitionCreator() {
throw new IllegalStateException("Utility class");
}
public static ApplicationMenuItemDefinition createMenuItem(String name,
String id,
List<MySubSubMenuItem> subSubMenuItems) {
return new ApplicationMenuItemDefinition(name, id,
Collections.singletonList(createSubMenuItem(subSubMenuItems)));
}
private static ApplicationMenuItemDefinition createSubMenuItem(List<MySubSubMenuItem> subSubMenuItems) {
String subMenuName = "New";
if (subSubMenuItems.size() > 1) {
return new ApplicationMenuItemDefinition(subMenuName, "new",
subSubMenuItems.stream()
.map(i -> new ApplicationMenuItemDefinition(i.getName(), i.getId(),
() -> i.getCommand().apply()))
.collect(Collectors.toList()));
} else if (subSubMenuItems.size() == 1) {
MySubSubMenuItem onlyItem = subSubMenuItems.get(0);
return new ApplicationMenuItemDefinition(onlyItem.getName(), onlyItem.getId(), onlyItem.getCommand());
} else {
return new ApplicationMenuItemDefinition(subMenuName, "new", Handler.NOP_HANDLER);
}
}
public static class MySubSubMenuItem {
private String name;
private String id;
public MySubSubMenuItem(String name, String id) {
this.name = name;
this.id = id;
}
public String getName() {
return name;
}
public String getId() {
return id;
}
public Handler getCommand() {
return () -> Notification.show(name);
}
}
}
To add a MenuItem
when to your own ApplicationMenu
or SubMenu
the following methods can be used:
-
createItem(ApplicationMenu)
: Creates and adds aMenuItem
to the givenApplicationMenu
. -
createItem(SubMenu)
: Creates and adds aMenuItem
to the givenSubMenu
.
ApplicationMenuItemDefinition startMenuItemDefinition = new ApplicationMenuItemDefinition("Start", () -> goToStart());
ApplicationMenu menuBar = new ApplicationMenu();
startMenuItemDefinition.createItem(menuBar);
ApplicationMenuItemDefinition itemDefinition = new ApplicationMenuItemDefinition("Start", () -> goToStart());
-- new MenuBar to create item for sub-menu
MenuBar menuBar = new MenuBar();
SubMenu subMenu = menuBar.addItem("item").getSubMenu();
itemDefinition.createItem(subMenu);
Default variants
The method getDefaultVariants
determines which variants of the linkki theme should be applied by default.
ErrorHandler
In case of an unhandled runtime exception, linkki shows information about the occurred error such as timestamp, a short description and a detailed stacktrace in a dialog. After confirming the dialog, the user is redirected to either the default main URL, or a custom error URL that can be set by extending the DialogErrorHandler
and pass it to the super
-constructor.
public class DialogErrorHandler implements ErrorHandler {
public DialogErrorHandler(BiFunction<ErrorEvent, Handler, ConfirmationDialog> dialogCreator, String startView) {
this.dialogCreator = dialogCreator;
this.startView = startView;
}
@Override
public void error(ErrorEvent event) {
ConfirmationDialog dialog = dialogCreator.apply(errorEvent, () -> UI.getCurrent().navigate(startView, QueryParameters.fromString("errorOccurred")));
dialog.open();
}
}
In addition, ApplicationLayout#getErrorHandler()
must be overridden to return your custom ErrorHandler
.
When redirecting, an additional errorOccurred
query parameter is added to the URL. This parameter enables the target view to react to the error. It can be useful in some cases to enable or disable certain features in BeforeLeaveHandler#beforeLeave(BeforeLeaveEvent)
in case of an error.
For more information refer to Vaadin’s BeforeLeaveEvent