new ApplicationMenuItemDefinition("Playground", 0) {
@Override
protected MenuItem internalCreateItem(ApplicationMenu menu) {
return menu.addItem(getName(), item -> LinkkiUi.getCurrentNavigator()
.navigateTo(PlaygroundView.NAME));
}
}
Vaadin 14 Migration
Application Framework
Messages
-
Deprecated
Message*classes have been removed-
MessageListPanelhas been replaced byMessageUiComponents#createMessageTable -
MessagePmohas been replaced byMessageRowPmo -
MessageRowhas been replaced byMessageUiComponents#createMessageComponent
-
LinkkiUi and navigation
Navigation has been replaced by Routing, using the @Route annotation at the corresponding Component itself. With the new changes, it is no longer necessary to extend the UI as the tasks of LinkkiUi either became oblivious or is overtaken by ApplicationLayout.
- LinkkiUi
-
Change Migration The class
LinkkiUiis removed.Remove sub-classes of
LinkkiUi.
- ApplicationLayout
-
Change Migration -
The constructor now takes
ApplicationConfigas a parameter. -
#getApplicationConfig` has been removed.
-
Create a new sub-class of
ApplicationLayout(e.g.MyApplicationLayout) -
In the new subclass, pass an instance of the customized
ApplicationConfigto the super constructor. ThisApplicationConfigwas previously used in the implementation ofLinkkiUi.
#createApplicationNavigatorhas been removed.No migration needed
ApplicationLayoutitself implementsRouterLayoutwhich make it possible to use theApplicationLayoutas the layout for routes, previously known as views. -
- ApplicationConfig
-
Change Migration The class is moved from
org.linkki.framework.statetoorg.linkki.framework.ui.application.Reorganize import in the project where
ApplicationConfigis used.ApplicationConfig#createApplicationLayouthas been removed.Move the implementation of
#createApplicationLayoutto the implementation ofApplicationLayout.Name, version, description and copyright are moved to
ApplicationInfo.-
Create a new implementation of
ApplicationInfothat contains the existing implementation for name, version, description and copyright.
If additional information needs to be stored to be displayed in the header and footer, follow the migration steps for theApplicationHeaderand theApplicationFooter. -
Return a instance of the new implementation in `ApplicationConfig#getApplicationInfo.
The return type
ApplicationHeaderDefinitionofApplicationConfig#ApplicationHeaderDefinitionhas changed:-
Until now: creates a
ApplicationHeaderfrom anApplicationMenu -
New: creates an
ApplicationHeaderfrom anApplicationInfoand a sequence ofApplicationMenuItemDefinitions.
-
If
getHeaderDefinitionwas not overridden, no migration is needed. -
If a custom implementation of
ApplicationHeaderwas used, consult migration steps of theApplicationHeader.
ApplicationConfig#ApplicationFooterDefinitionhas changed: * Until now: creates aApplicationFooterfrom anApplicationConfig* New: creates anApplicationFooterfrom anApplicationInfo-
If
getFooterDefinitionwas not overridden, no migration is needed. -
If a custom implementation of
ApplicationFooterwas used, consult migration steps of theApplicationFooter.
-
- ApplicationHeader
-
If no custom implementation of
ApplicationHeaderis used, no migration is needed.
In custom implementations:Change Migration ApplicationHeader#addUserMenuThe user menu has been completely removed. This has to be implemented by yourself.If you want to create a user menu, then overwrite
ApplicationHeader#createRightMenuBarand add aMenuItemto theMenuBarApplicationHeaderuses anApplicationInfoandSequence<ApplicationMenuItem>as arguments instead ofApplicationMenu.Adjust the constructor and the super constructor call within with the new parameters.
ApplicationHeadernow extendsComposite<HorizontalLayout>instead ofHorizontalLayoutdirectly.Whenever components are added, add the components to
getContent()instead.ApplicationInfoPmousesApplicationInfoas constructor argument instead ofApplicationConfigIn a custom
ApplicationInfoPmoimplementation is used:-
In subclasses of
ApplicationInfoPmo, adjust the constructor and the super constructor call within with the new parameters. -
If
ApplicationHeader#getApplicationInfo, change the return type to the custom subclass. -
In
ApplicationHeader#createApplicationInfoPmo, use the adjusted constructor with#getApplicationInfo.
ApplicationHeader#addRightComponents()visibility has changed fromprotectedtoprivatedue to deprecation.In the subclasses, override and move the code to
addRightComponents(HorizontalLayout).API of
ApplicationMenuItemDefinitionhas changed, resulting in changes ingetMenuItemDefinitions.See migration steps of the ApplicationMenuItemDefinition.
-
- ApplicationMenuItemDefinition
-
The API of
ApplicationMenuItemDefinitionis completely reworked. Instead of extending the class for customization, the new API is intended to be easily composable for customization.Change Migration Argument
positionis removed from the constructor as it was not necessary.Remove the attribute. To ensure the position of the menu item, make sure to put it at the right position in
ApplicationConfig#getMenuItemDefinitions.getNameis removed.Pass the name to the constructor directly instead.
The methods
createItemandinternalCreateItemare removed. Instead, new constructors are introduced:-
with name and a
Handlerthat is executed on click. -
with name and a list of
ApplicationMenuItemDefinitionsas sub-menu items -
with name and a URL String to navigate to on click. This method handles both external and internal links.
-
with name and a
Classto navigate to. The given class should be a route component.
Use the existing implementation of
internalCreateItemandcreateItemto directly create new instances ofApplicationMenuItemDefinition. A few examples are provided below.The following code snippet shows a simple
ApplicationMenuItembefore and after migration:Table 1. Migration of a simple ApplicationMenuItem Before migration After migration new ApplicationMenuItemDefinition("Playground", PlaygroundApplicationView.class)For more complex menu items that used to extend from
ApplicationMenuItem, consider create menu item definitions directly instead of inheriting. If the implementation need to be customizable, it can be easily done by composingApplicationMenuItems.
Here is an example of a more complexApplicationMenuItem. This 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).Table 2. Migration of a complex ApplicationMenuItem Before migration After migration public class CustomMenuItemDefinition extends ApplicationMenuItemDefinition { private List<MySubSubMenuItem> subSubMenuItems; public CustomMenuItemDefinition(String name, int position, List<MySubSubMenuItem> subSubMenuItems) { super(name, position); this.subSubMenuItems = subSubMenuItems; } private List<MySubSubMenuItem> getSubSubMenuItems() { return subSubMenuItems; } @Override protected MenuItem internalCreateItem(ApplicationMenu menu) { MenuItem newApplicationMenuItem = menu.addItem(getName(), null, null); MenuItem newMenuItem = newApplicationMenuItem.addItem("New", null); if (getSubSubMenuItems().size() > 1) { getSubSubMenuItems().forEach(i -> newMenuItem.addItem(i.getName(), i.getCommand())); } else if (getSubSubMenuItems().size() == 1) { MySubSubMenuItem onlyItem = getSubSubMenuItems().get(0); newMenuItem.addItem(onlyItem.getName(), onlyItem.getCommand()); } return newApplicationMenuItem; } public static class MySubSubMenuItem { private String name; public MySubSubMenuItem(String name) { this.name = name; } public String getName() { return name; } public Command getCommand() { return i -> Notification.show(name); } } }public class CustomMenuItemDefinitionCreator { public static ApplicationMenuItemDefinition createMenuItem(String name, List<MySubSubMenuItem> subSubMenuItems) { return new ApplicationMenuItemDefinition(name, Collections.singletonList(createSubMenuItem(subSubMenuItems))); } private static ApplicationMenuItemDefinition createSubMenuItem(List<MySubSubMenuItem> subSubMenuItems) { String subMenuName = "New"; if (subSubMenuItems.size() > 1) { return new ApplicationMenuItemDefinition(subMenuName, subSubMenuItems.stream() .map(i -> new ApplicationMenuItemDefinition(i.getName(), () -> i.getCommand().apply())) .collect(Collectors.toList())); } else if (subSubMenuItems.size() == 1) { MySubSubMenuItem onlyItem = subSubMenuItems.get(0); return new ApplicationMenuItemDefinition(onlyItem.getName(), onlyItem.getCommand()); } else { return new ApplicationMenuItemDefinition(subMenuName, Handler.NOP_HANDLER); } } public static class MySubSubMenuItem { private String name; public MySubSubMenuItem(String name) { this.name = name; } public String getName() { return name; } public Handler getCommand() { return () -> Notification.show(name); } } } -
- Views
| Change | Migration |
|---|---|
|
Remove the interface in all implementations. |
Views must be annotated with |
Annotate all views with |
- Other changes
-
-
ApplicationNavigatorhas been removed
-
Components
-
linkki dialogs are now extending
Composite<Dialog>instead ofWindow. -
MessageUiComponentsare now displayed usingGridinstead ofTable
TabSheetArea has been replaced by LinkkiTabLayout
-
TabSheetArea#addTab→LinkkiTabLayout#addTabSheet -
TabSheetArea#createContentto add tabs usingTabSheetArea#addTabhas been removed. Instead,LinkkiTabLayout#addTabSheetshould be used -
TabSheetArea#updateContenthas been removed.
SidebarLayout has been replaced by LinkkiTabLayout
-- Vaadin 8
SidebarLayout sidebarLayout = new SidebarLayout();
-- Vaadin 14
LinkkiTabLayout linkkiTabLayout = LinkkiTabLayout.newSidebarLayout();
-
SidebarLayout#addSheet→LinkkiTabLayout#addTabSheet -
SidebarLayout#addSheets→LinkkiTabLayout#addTabSheets -
SidebarLayout#addSelectionListener→LinkkiTabLayout#addSelectedChangeListener -
SidebarLayout#select(id)→LinkkiTabLayout#setSelectedTabSheet(sheet.getId()) -
SidebarLayout#select(sheet)→LinkkiTabLayout#setSelectedTabSheet(sheet.getId()) -
SidebarLayout#getSelected→LinkkiTabLayout#getSelectedTabSheet -
SidebarLayout#getSidebarSheet(id)→LinkkiTabLayout#getTabSheet(id) -
SidebarLayout#getSidebarSheets→LinkkiTabLayout# getTabSheets -
SidebarSelectionEvent#getOldValue→SelectedChangeEvent#getPreviousTab -
SidebarSelectionEvent#getSelectedSheet→SelectedChangeEvent#getSelectedTab
Tab visibility can be controlled using LinkkiTabSheetBuilder#visibleWhen and LinkkiTabLayout#updateSheetVisibility.
SidebarSheet has been replaced by LinkkiTabSheet
For performance reasons, components must be created via a supplier and can no longer be set directly.
-- Vaadin 8
SidebarSheet sidebarSheet = SidebarSheet(id, icon, name, contentSupplier, uiUpdateObserver);
-- Vaadin 14
LinkkiTabSheet linkkiTabSheet = LinkkiTabSheet.builder(id)
.caption(icon.create()) //.caption(String)
.description(name)
.content(contentSupplier)
.onSelectHandler(uiUpdateObserver)
.build();
-
SidebarSheet#getButton().getIcon()→LinkkiTabSheet#getTab().getChildren().findFirst().get() -
SidebarSheet#getName→LinkkiTabSheet#getDescription
@UIButton
-
styleNames()has been replaced byvariants(), which now returns an Array ofButtonVariant -
shortcutKeyCodenow returnsString[]. Commonly usedKeyCodesin linkki are defined inKeyCode. An overview of all supported keys can be found in Vaadin’sKeyclass. -
shortcutModifierKeysnow returns an Array ofKeyModifier. For a list of available modifiers, see Vaadin’s enum classKeyModifier.
@UIDateField
The date format of a @UIDateField is now controlled by DateFormats and the locale, the attribute dateFormat has been removed.
@UITextArea
Attribute rows does not exists anymore. It has been replaced by height, which returns a String, specifying the height of the component using a number and a CSS unit, for example "5em".
@UILabel
The usage of the ContentMode for @UILabel in Vaadin 8 has changed. Instead of setting Label#setContentMode to true when using Label#htmlContent , you can use getElement().setProperty("innerHTML", "<b>My html content</b>") of the corresponding component, as now used in linkki LabelValueAspectDefinition.
For a further example, see https://vaadin.com/forum/thread/17133860/label-contentmode-html
ComponentFactory
Following *Label methods have been removed, as Label has been replaced by LinkkiText:
-
newLabelWidth100(parent, caption) -
sizedLabel(parent, caption, contentMode) -
sizedLabel(parent, caption) -
newLabelWidthUndefined(parent, caption) -
labelIcon(parent, fontIcon) -
newEmptyLabel(layout) -
newLabelIcon(fontIcon) -
newLabelFullWidth(caption, contentMode) -
newLabelFullWidth(caption) -
newLabelUndefinedWidth(caption, contentMode) -
newLabelUndefinedWidth(caption)
Component#setIcon
The setIcon method for Component has been deleted. It is only available for @UIButton and components, that are implementing the HasIcon interface, like the ones created by @UILabel and @UILink.
Resource / Icon
com.vaadin.server.Resource for icons in Vaadin 8 has been replaced by VaadinIcon#create
Tables have been replaced by Grids
In Vaadin 14, Table has been replaced by Grid
-
PmoBasedTablefactoryhas been replaced byGridComponentCreator -
@UITableColumn:expandRatioreplaced byflexGrow. TheflexGrowspecifies what amount of the available space inside the table the column should take up and grow (if resized), proportionally to the other columns. IfflexGrowis set to 0, the column has a fixedwidth.
Aspect annotations
@BindIcon
The @BindIcon annotation is available for @UIButton and all components, that are implementing the HasIcon interface. At the moment, these are @UILabel and @UILink. Using htmlContent of the @UILabel will override any icon.
NLS
TextProvider
It is recommended to provide an implementation of I18NProvider as following, to ensure UI#getLocale returns the best matching Locale corresponding to the user agent’s preferences (i.e. the Accept-Language header). If no I18NProvider is available, the default JVM Locale is used.
@Component
public class MyI18NProvider implements I18NProvider {
...
}
Styling
Theming
Valo theme has been replaced by Lumo theme. For more information see https://vaadin.com/docs/flow/migration/6-theming.html
Tooltips
By now, tooltips are only supported by LinkkiTabSheet, using the LinkkiTabSheet#description property. Other UI components currently do not support tooltips. For more information see https://vaadin.com/forum/thread/17094165/tooltips
Notifications
See Notifications
ComponentStyles
In Vaadin 8, sections created with @UISection have a dynamic label width by default, i.e. the labels are as long as the longest label.
For @UIFormSection, LinkkiTheme offered style names to set a fixed width.
This behavior has changed with Vaadin 14. All sections now have a fixed label width by default. It is not possible to have dynamic label width anymore.
To set a custom label width, you can use ComponentStyles.setFormItemLabelWidth(Component, String).
This replaces the class names LinkkiTheme.LABEL_FIXED_WIDTH and LinkkiTheme.LABEL_FIXED_WIDTH_LONG.
| Before migration | After migration |
|---|---|
|
|
To apply a custom label width to all sections inside a Component, the surrounding layout such as AbstractPage can be passed as the Component-Parameter.
For more information see ComponentStyles.