A collection of extension functions mimicking Vaadin 8 API but redirecting to Vaadin 14+ API where applicable.
This simplifies the process when rewriting Vaadin 8 components/layouts/view to Vaadin 14, since
you can continue using the same Vaadin 8 functions and get useful information and warnings.
For example,
there is setWidthUndefined() function marked as deprecated (since it's no longer in Vaadin 14), redirecting to a setWidth(null) call.
The jar is in Maven Central, so it's easy to add this library to your project.
Gradle:
repositories {
mavenCentral()
}
dependencies {
api("com.github.mvysny.karibu-migration:karibu-migration-MODULE:x.y")
}Maven:
<dependency>
<groupId>com.github.mvysny.karibu-migration</groupId>
<artifactId>karibu-migration-MODULE</artifactId>
<version>x.y</version>
</dependency>See the tag above for the latest version.
There are two modules available:
- The
karibu-migration-commonmodule is pure Java, doesn't depend on Kotlin and brings in a set of compatibility-helping components:GridLayout,HtmlSpan,HorizontalSplitPanel,NativeSelect,RadioButtonGroupCompat,SplitLayoutCompat,VerticalSplitPanel,LabelWrapperand others. - The
karibu-migration-kotlinbuilds onkaribu-migration-commonand adds lots of useful Kotlin extension methods to Vaadin 14+ components which emulate Vaadin 8 API. If you ever wanted to convert your Vaadin 8 project to Kotlin and clean it up, it's smart to do that before the migration - you'll gain access to these extension methods, and you will not have to convert obsolete crap code.
The official Vaadin documentation on migration:
- Upgrading from Vaadin 8 lists general strategies
- Replacement components - a list of all Vaadin 8 components and their replacement counterparts in Vaadin 14.
Usually, the upgrade is done one of the following ways:
- Employing the Multiplatform Runtime which allows
you to embed Vaadin 8 components into Vaadin 14 components (but not vice versa). The strategy
is as follows:
- Convert your app shell (the main route layout) to Vaadin 14, while nesting all Vaadin 8 views in Vaadin 14 wrapper components.
- Convert your views one-by-one to Vaadin 14.
- For Vaadin8+14 MPR demo project see Vaadin 14 MPR + Vaadin 8 Gradle Demo Project; Maven version Tatu Lund's mpr-demo.
- Adding a secondary Vaadin 14 servlet on classpath, then running Vaadin 8 app alongside the new Vaadin 14 app.
In all cases, the application needs to be converted manually, view-by-view, to Vaadin 14.
Vaadin 8 apps and components were styled by adding rules to the global SCSS file, then adding styles to individual components. That is possible with Vaadin 14 as well, but there are very important distinctions:
- Many of the components styles are now applied via theme variants. For example, the
ValoTheme.COMBOBOX_SMALLis now applied viaaddThemeVariants(ComboBoxVariant.Small); adding theValoTheme.COMBOBOX_SMALLviaaddClassName()would have no effect.- To see available theme variants for particular components, find the component at the Vaadin Components page, then go to the "Examples" / "Theme Variants" tab.
- It's not possible to style component internals via a global CSS because of Web component mechanism called the Shadow DOM. Read more at Vaadin official documentation on Style Scopes.
- Other than that, you can still use the global styles if needed. You can't use SCSS though (well you can but then you have to figure out
how to compile SCSS yourself - there's no direct support for SCSS in Vaadin 14+ anymore), and you have to apply classes via
addClassName()instead ofaddStyleName().
I really urge you to read the Styling and Themes chapter, to familiarize yourself with the new concepts.
Vaadin 8's Valo theme has been replaced by Vaadin 14's Lumo theme. Theme parametrization is done via CSS Variables rather than the SCSS mechanism. Find more information here:
- The Lumo documentation lists all variables
- The Lumo Editor offers a great way to play with the variables and see the outcome in realtime.
- See Vaadin 8 Sampler for the way how Vaadin 8 components looked like with Valo theme
- For a complete list of Vaadin 8 components, along with all ValoTheme variants, see the "UITest" project at karibu-dsl page.
HasSize.setWidthUndefined()is replaced bysetWidth(null)HasSize.setHeightUndefined()is replaced bysetHeight(null)Component.setCaption()is replaced byComponent.setLabel()from karibu-tools.- Warning: in order for the caption to be visible, the component must be nested in
VerticalLayout/HorizontalLayout/FlexLayout. - Alternatively, wrap the component in the
LabelWrappercomponent decorator fromkaribu-migration-common. - See more at Vaadin 8->14 Counterparts blogpost
- Warning: in order for the caption to be visible, the component must be nested in
Component.getCaption()is replaced byComponent.getLabel()from karibu-tools.CssLayoutis replaced by aDivComponent.setDescription()is replaced byComponent.setTooltip()from karibu-tools, which sets thetooltipDOM attribute. However this doesn't support tooltips with HTML; you can alternatively use vcf-tooltip.Component.getDescription()is replaced byComponent.getTooltip()from karibu-tools, which reads thetooltipDOM attribute.- Styles:
setStyleName()replaced bysetClassName;addStyleName()replaced byaddClassName();removeStyleName()replaced byremoveClassName()addStyleName(ValoTheme.*)is generally replaced byaddThemeVariants(XYZVariant.LUMO_*)- IMPORTANT: The styles mechanism has been redesigned completely; read the Styles chapter for more information.
- Children:
removeAllComponents()- replace byremoveAll()addComponent()- replace byadd()removeComponent()- replace byremove()
It is discouraged to have a custom UI class. If this is necessary, it's better to
create a separate utility class and store it into the UI instance via ComponentUtil.setData(UI.getCurrent(), Util.class, util).
Alternatively see How to correctly extend a UI.
UI.getUiRootPath()- prints the context root with the leading slash, e.g./Gradle___karibu_helloworld_application_warand so it’s perfect for creating navigational links. Replaced withVaadinRequest.getCurrent().getContextPath().UI.setMobileHtml5DndEnabled()- No longer necessary: mobile html 5 Drag'n'drop is enabled automatically on Vaadin 14+. Read Drag and drop on mobile devices for more info.
setItemCaptionGenerator()is replaced bysetItemLabelGenerator()- use
addThemeVariants(ComboBoxVariant.Small)instead ofValoTheme.COMBOBOX_SMALL. - Use
addThemeVariants(ComboBoxVariant.AlignRight)from karibu-tools instead ofValoTheme.COMBOBOX_ALIGN_RIGHT - Use
addThemeVariants(ComboBoxVariant.AlignCenter)from karibu-tools instead ofValoTheme.COMBOBOX_ALIGN_CENTER - There are no direct replacements for
ValoTheme.COMBOBOX_TINY,ValoTheme.COMBOBOX_LARGE,ValoTheme.COMBOBOX_HUGEandValoTheme.COMBOBOX_BORDERLESS. setEmptySelectionAllowed()- Whenallowedwas set to true, the Vaadin 8 ComboBox used to show an additional item representing thenullvalue. This is hard to emulate via DataProvider; the easiest replacement is to simply show or hide the clear button. Also see Adding support for null values to Vaadin ComboBox for more details.- Given that, replace
setEmptySelectionCaption()withsetPlaceholder(). setTextInputAllowed()- no replacement. ComboBox always allows text input. UseSelectinstead if you want to disable text input.scrollToSelectedItem()- no replacement as of today. Please open a feature request at flow-components/issues.
Also take a look at the ComboBox with Vaadin 8 behavior which closely mimics Vaadin 8 ComboBox.
setItemCaptionGenerator()is replaced bysetItemLabelGenerator()
There's also NativeSelect Vaadin 14 component for your convenience, which simply
extends Vaadin 14's Select but provides all constructors from Vaadin 8's NativeSelect.
setItemCaptionGenerator()is replaced bysetItemLabelGenerator()
setItemCaptionGenerator()is replaced bysetItemLabelGenerator()from karibu-tools- No replacement for
OPTIONGROUP_SMALLandOPTIONGROUP_LARGE - RadioButtonGroup is horizontal by default; use
addThemeVariants(RadioGroupVariant.LUMO_VERTICAL)to lay out buttons horizontally in absence ofValoTheme.OPTIONGROUP_HORIZONTAL.
This project provides the RadioButtonGroupCompat class which introduces a better Vaadin 8 compatibility:
setItemDescriptionGenerator()setHtmlContentAllowed()- It is vertical by default; also adds
setVertical(boolean)utility setter.
It's not possible to have a single RadioButton just as it's not possible with Vaadin 8. See+vote for issue 1952. Workaround is to have a RadioButtonGroup with just one item.
Grid:
isSelectionAllowed()- replace withisSelectionAllowedfrom karibu-tools. Essentially check if the selection model is eitherSelectionModel.MultiorSelectionModel.Single.Grid.addFooterRowAt(index)- no replacement; the extension function calls eitherprependFooterRow()orappendFooterRow().Grid.getFooterRowCount()- replace withgetFooterRows().size().Grid.getHeaderRowCount()- replace withgetHeaderRows().size().Grid.setExpandRatio()- replace withsetFlexGrow().
Grid.Column:
Column.setDescriptionGenerator()- no replacement. See issue #2315Column.setExpandRatio()- replace withsetFlexGrow()Column.getExpandRatio()- replace withgetFlexGrow()Column.setCaption()- replace withsetHeader()Column.getCaption()- no replacement, see issue #1496- NOTE: Grid.Column now expands by default; if you want to set it to a fixed width
then you have to call
setWidth("50px").setFlexGrow(0). Column.setHidden()- replace withsetVisible()Column.isHidden()- replace withisVisible()Column.setHidable()- No replacement as of now; see+vote for issue #1603Column.isHidable()- no replacement as of now
- The
addContextMenuOpenListener()has been replaced byaddGridContextMenuOpenedListener(). WARNING: weird bugs will happen if you try to dynamically populate menu contents from this listener - see grid #575. Make sure to usesetDynamicContentHandler()instead.
The way how HorizontalLayout and VerticalLayout works has been changed completely. There is no slot mechanism anymore, and the layouting is now based on CSS Flexbox rather than on a Vaadin-specific JavaScript code. You need to relearn how CSS Flexbox works, then rework your layouts to work on top of CSS Flexbox. Docs to read:
- Vaadin docs: Layouts in Platform
- Vaadin 10 server-side layouting for Vaadin 8 and Android developers
API replacements:
setExpandRatio(): replace with eitherexpand()(if the expand ratio is 1) orsetFlexGrow()addComponentsAndExpand(): replace withaddAndExpand()
A compatibility replacement components are coming, as a Vaadin Pro feature (TBA).
Please see the GridLayout class providing Vaadin 8 API. Note that the new GridLayout
doesn't use slots and therefore uses different layouting engine. It's merely provided
as a best-effort.
Alternatively see the GridLayout from Vaadin Directory - it supports slots (which means positioning of children within allotted cells) but no expand ratios at the moment.
Label is no longer a Div but an actual <label> element. Usually the best approach is
to replace label by Div or Span.
new Label("", ContentMode.HTML)is replaced bynew HtmlSpan()fromcommonLabelwithValoTheme.LABEL_H1is replaced bynew H1(); similar forH2/H3/H4/H5/H6.ValoTheme.LABEL_HUGE,ValoTheme.LABEL_LARGE,ValoTheme.LABEL_SMALL,ValoTheme.LABEL_TINY- no replacements.ValoTheme.LABEL_BOLD-> replace withgetStyle().set("font-weight", "500")ValoTheme.LABEL_LIGHT-> used to set lighter text color and a font weight of 200, no replacement.ValoTheme.LABEL_COLORED-> sets a blue text color#197de1, no replacement.ValoTheme.LABEL_SUCCESS/LABEL_FAILUREused a green/red text color and a border, no replacement.ValoTheme.LABEL_SPINNER-> use an indeterminate Progress Bar.
Vaadin 8's CustomField sets its width to 100% by default while Vaadin 10+'s CustomField wraps its children by default.
Make sure to have your CustomField implement HasSize and call this.setWidthFull().
Not available directly. You can either build your own component out of Vaadin 14 Tabs+Tab
(but that's just the tab header area), or try to use:
TabSheetfromkaribu-migration-common(a direct replacement)TabSheetfrom karibu-dsl (the same thing but in Kotlin with DSL support)- paged-tabs Vaadin Directory extension
- kinda works but the API is not that rich compared to Vaadin 8's TabSheet.
Use the VerticalSplitPanel and HorizontalSplitPanel classes extending the Vaadin 14 SplitLayout
providing the old Vaadin 8 API. Note that only Unit.PERCENTAGE is supported -
trying to use Unit.PX will fail with an exception.
Sorry, no replacement at the moment. TBD
Replace with MultiSelectListBox. There is also a ListSelect component provided by karibu-migration-common which mimics Vaadin 8 version.
setItemCaptionGenerator()- implemented inListSelect; replaced bysetRenderer(new TextRenderer<>(itemLabelGenerator));. See+vote on issue #2601. Also replaced by Karibu-Tools'sListBoxBase.setItemLabelGenerator().
ClassResource- replace with StreamResourceThemeResource- You have two options:- you can store the image into the theme folder; then you can refer to the image from a CSS file as per
Creating a custom theme/Other Assets.
You can also refer to the image via
new Image("themes/my-theme/img/foo.png", "foo")if you store the image to/frontend/themes/my-theme/img/foo.png- Vaadin will copy the static resources to your WAR archive, to the/META-INF/VAADIN/webapp/VAADIN/static/themes/my-theme/img/foo.pngfolder and will serve the images from there. - Alternatively you can place the images
into the static resource folder (usually
src/main/webapp; the image would then go tosrc/main/webapp/img/foo.png) then refer to the image vianew Image("img/foo.png"). See the Resource cheat sheet for more info. - Make sure to refer to the images as
new Image("img/foo.png")and notnew Image("/img/foo.png")nornew Image("./img/foo.png")- the first one would not work with a non-empty context root while the latter one will stop working for nested routes such as@Route("my/nested/route").
- you can store the image into the theme folder; then you can refer to the image from a CSS file as per
Creating a custom theme/Other Assets.
You can also refer to the image via
- Add extension functions for Groovy
- Add extension functions for Lombok
- Document all Vaadin 8 components in this README. Please create PRs to create a definitive migration guide here 👍
Licensed under Apache 2.0
Copyright 2021-2022 Martin Vysny
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this software except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
See Contributing.