-
The constructor now takes
ApplicationConfigas a parameter. -
#getApplicationConfig` has been removed.
Vaadin 8 to Flow 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 -
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, id and a
Handlerthat is executed on click. -
with name, id and a list of
ApplicationMenuItemDefinitionsas sub-menu items -
with name, id and a URL String to navigate to on click. This method handles both external and internal links.
-
with name, id 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 @Override public Sequence<ApplicationMenuItemDefinition> getMenuItemDefinitions() { return Sequence.of( new ApplicationMenuItemDefinition("Playground", 0) { @Override protected MenuItem internalCreateItem(ApplicationMenu menu) { return menu.addItem(getName(), item -> LinkkiUi.getCurrentNavigator() .navigateTo(PlaygroundView.NAME)); } }); }new ApplicationMenuItemDefinition("Playground", "playground", TestScenarioView.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 { 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); } } } -
| Change | Migration |
|---|---|
|
Adjust the constructor and the super constructor call within with the new parameters. |
|
Whenever components are added, add the components to |
|
Adjust the implementation of |
|
In subclasses, override and move the code to |
Visibility of |
This method should not be called externally anymore. Remove external calls. |
- Views
| Change | Migration |
|---|---|
|
Remove the interface in all implementations. |
Views must be annotated with |
Annotate all views with |
- Other changes
-
-
ApplicationNavigatorhas been removed
-
Components
-
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
| Before migration | After migration |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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.
| Before migration | After migration |
|---|---|
|
|
|
|
|
|
*UiUpdateObserver has been replaced by AfterTabSelectedObserver. For more information see AfterTabSelectedObserver.
@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".
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 Flow, 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.
Notifications
In Vaadin 8, there used to be four types of notification: humanized, warning, error and tray. This categorization does not exist anymore. To display notifications based on the severity, linkki provides a new class NotificationUtil. See the documentation on notifications for more detail.
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.
@BindTooltip
HTML content is no longer support for tooltips.
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
In general, the the Sass precompiler is no longer used by default, which means that any existing styling code that utilized SCSS functionalities needs to be adjusted to work in CSS.
In addition, all applications need to either apply the "linkki" theme or a theme that extends from it to make sure that the linkki components work properly. Detailed instructions are provided in the chapter "Styling".
As the generated HTML has changed drastically, existing styling customizations have to be checked for necessity and, if still necessary, adjusted for the new DOM structure. As Vaadin components are now mostly web components, existing styles that apply to Vaadin components most likely do not work any more. Consult the Vaadin documentation on component styling to adjust the selectors and the documentation on theming for how to include them in the custom theme.
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 Flow. 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.
Views
PageTitle
In order to set a page title for a view, the View class has to be annotated with either @PageTitle or has to implement the HasDynamicTitle interface.
For more Information see Updating the Page Title During Navigation