Upgrade Guide Generator
Instructions for upgrading to the latest Vaadin version. To run applications or components developed with Vaadin 7 or 8 inside an application written using the latest version, see Multiplatform Runtime.
Before You Start
-
Delete the
node_modulesfolder and either lock file:package-lock.json(withnpm) orpnpm-lock.yaml(withpnpm). -
Edit the
pom.xmlfile and change the Vaadin version tonew version.
-
Update Spring Version.
Vaadin is compatible with Spring 5.3.18 or later, and Spring Boot 2.6.6 or later. If your application uses an older version of Spring, update it to a compatible version:
Source code
pom.xml
pom.xml<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.6</version>
</parent>Upgrading the Spring version might require some non-Vaadin-related changes to your application. See Spring Boot release notes for the list of required changes.
Vaadin 14 to 23 Upgrade Guide
The 14-to-23 upgrading instructions are available in the following separate chapter.
Upgrade Steps | 14 → 15
Update Main Layout/View Annotations
Several annotations typically placed on the MainLayout / MainView class must be moved to a class that implements the AppShellConfigurator interface, for example:
Source code
Java
@PWA(name = "My Vaadin App", shortName = "my-app")
public class AppShell implements AppShellConfigurator {
}see set of annotations to modify the Bootstrap page for more details.
Replace Obsolete APIs
A set of API breaking changes and their replacements are listed below:
-
Property synchronization methods in
Elementare replaced with similar API inDomListenerRegistration:getSynchronizedPropertyEvents,getSynchronizedProperties,removeSynchronizedPropertyEvent,removeSynchronizedProperty,addSynchronizedPropertyEvent,addSynchronizedProperty,synchronizeProperty. -
JavaScript execution APIs
executeJavaScriptandcallFunctioninElementandPageare replaced with similarly named methods that give access to the return valueexecuteJsandcallJsFunction: -
Miscellaneous
Elementmethods:Element(String, boolean),addEventListener(String, DomEventListener, String…) -
Device and platform detection methods
WebBrowser#isIOS(),WebBrowser#isIPad(),BrowserDetails#isSafariOrIOS(),BrowserDetails#isIOS(),BrowserDetails#isIPad()are replaced with method inExtendedClientDetails:isIPad(),isIOS() -
Methods
JsModule#loadMode()andPage#addJsModule(String, LoadMode)for setting the load mode of JsModule are removed since it doesn’t function with JavaScript modules. -
The construction methods
BeforeEvent(NavigationEvent, Class<?>)andBeforeEvent(Router, NavigationTrigger, Location, Class<?>, UI)inBeforeEventare replaced withBeforeEvent(NavigationEvent, Class, List)andBeforeEvent(Router, NavigationTrigger, Location, Class, UI, List) -
Methods
getUrl(),getUrlBase()andgetRoutes()inRouterare replaced with methodsgetUrl(),getUrlBase()andgetAvailableRoutes()inRouterConfiguration. Theresolve()method inRouteris replaced with theresolve()method inRouteUtil. ThegetRoutesByParent()method inRouteris removed and has no replacement. -
ServletHelperis replaced withHandlerHelper -
ExecutionCanceleris replaced withPendingJavaScriptResult -
The
getBodyAttributesmethod inAbstractTheme,LumoandMaterialis replaced withgetHtmlAttributes -
The
removeDataGeneratormethod inHasDataGeneratorsandCompositeDataGeneratoris removed in favor of using the registration returned fromaddDataGenerator(DataGenerator) -
The methods
preventsDefaultandstopsPropagationinShortcutRegistrationare replaced withisBrowserDefaultAllowed ` and `isEventPropagationAllowed -
The
safeEscapeForHtmlmethod inVaadinServletis removed in favor of usingorg.jsoup.nodes.Entities#escape(String) -
The static method
getInstanceinApplicationRouteRegistryis removed in favor of the instance method. -
The protected instance method
getApplicationUrlfromVaadinServletis removed
Bootstrapping Changes
For applications upgraded from earlier versions of Vaadin, client-side bootstrapping requires replacing the usages of the V10-14 BootstrapHandler APIs with their IndexHtmlRequestHandler API counterparts as described in IndexHtmlRequestListener interface section.
The reason for this API change is that with client-side bootstrapping the initial page HTML generation is separated from loading the Flow client and creating a server-side UI instance.
-
In Vaadin 10 to 14 these two steps are combined and the
index.htmlpage includes the code and configuration needed to start the Flow client engine and link the browser page to the server-sideUIinstance. -
In Vaadin 15+ with client-side bootstrapping the
index.htmlpage includes only the basic HTML markup and links to the TypeScript UI code. If you have Hilla views, theUIisn’t guaranteed to be created, thus is optional. It’s only available after the user navigates to a server-side route.
It’s also possible to continue using the bootstrapping mode in V10-14 with the useDeprecatedV14Bootstrapping flag.
See how the use the flag in Configuration Properties.
-
Vaadin Fusion doesn’t involve any API breaking changes between versions 14 and 15. See the release notes at https://github.com/vaadin/platform/releases/tag/15.0.0.
Upgrade Steps | 15 → 16
Vaadin 16 doesn’t involve any API breaking changes. See the release notes at https://github.com/vaadin/platform/releases/tag/16.0.0.
Upgrade Steps | 16 → 17
Move Annotations to AppShellConfigurator
The only place where configuring the application with certain annotations is supported is in a class that implements AppShellConfigurator.
This applies for v15+ bootstrap mode (the default), but not for v14 legacy bootstrapping.
Rather than showing nondeterministic behavior and logging an error, the build fails when any of the following annotations occur outside an AppShellConfigurator class:
Source code
Meta.class, PWA.class, Inline.class, Viewport.class, BodySize.class, Push.classReplace Obsolete APIs
A New API for Binding Items to Components:
-
HasDataProviderandHasItemsare now replaced by the newHasListDataView,HasLazyDataViewandHasDataViewinterfaces inGrid,SelectandCheckBoxGroup. It’s also gradually replaced in other components which have an items binding. -
setDataProvider()is now deprecated and it’s recommended to use overloadedsetItems()methods. -
setItems()methods now have a return type instead of void. -
the
HasItemsAndComponentsinterface has been replaced byHasItemComponentsto support the Data View API in in-memory binding components. -
HasHierarchicalDataProviderno longer hassetItems()overloads forCollection,StreamandArray.
URL Parameters Template Feature
-
BeforeEventhas a bunch of new methods for forwarding, rerouting and getting the parameters. Some methods are now deprecated or removed. -
The
RouteRegistryandSessionRouteRegistryinterfaces are now supplemented with new methods and deprecate getters for route layouts. -
com.vaadin.flow.server.startup.RouteTargethas been completely removed. This class was internal and shouldn’t have been used. If you have been using it, you can create an issue describing what you needed it for.
Upgrade Steps | 17 → 18
-
Using
LitTemplateis recommended over the deprecatedPolymerTemplateto do layouts with HTML and UI logic in Java.
It’s recommended to use TypeScript for the template and this has been updated to the examples in the documentation.
-
Starting from Vaadin 18, the initial attribute values in the template are reflected to the server side state when
@Idmapping components. This applies toPolymerTemplate, too. More information on the template support is available in this blog post.
Flow Breaking Changes
-
AppShellRegistrymethodgetTitle()is removed It was broken and couldn’t work. Instead, if needed, usegetUI().getUIInternals().getAppShellTitle(). -
Having the
@Themeannotation on Flow views or router layouts is no longer allowed. The annotation should be onAppShellConfiguratorinstead. This is now consistent with the@PWAannotation. It’s also cleaner, since you can only have one@Themeper application. -
AbstractListDataViewnow requires an extra constructor argument - a callback, which is invoked each time when the component’s filter and/or sorting changes through the data view API.
Fusion Breaking Changes
-
The
valueproperty ofBinderNodenow has optionallyundefinedtype for non-initialized optional fields.
Upgrade Steps | 18 → 19
-
Vaadin Flow doesn’t involve any API breaking changes between versions 18 and 19. See the release notes at https://github.com/vaadin/platform/releases/tag/19.0.0.
Fusion Breaking Changes
Generated @Id Field Is Now of Optional Type in TypeScript
A field with @Id annotation in Java is now of optional type in the generated TypeScript code.
Given an entity with an id field:
Source code
Entity.java
Entity.javapublic class Entity {
@Id
private int id;
}Now in the TypeScript files, instead of using endpoint.getEntity(entity.id), you might need to change to endpoint.getEntity(entity.id!) (if you know that the id is always set when this is called) or add a type guard to explicitly check that id isn’t undefined.
Ignore One More Service Worker Related Static File
You need to ignore one more static file, /sw-runtime-resources-precache.js, if you use HttpSecurity.authorizeRequests() to do role-based authorization in your security configuration as follows:
Source code
SecurityConfiguration.java
SecurityConfiguration.java@Override
protected void configure(HttpSecurity http) throws Exception {
...
http.authorizeRequests().anyRequest().hasAnyAuthority(Role.getAllRoles());
...
}In this situation, you need to add one more file /sw-runtime-resources-precache.js to the static resource list that Spring Security bypasses:
Source code
SecurityConfiguration.java
SecurityConfiguration.java@Override
public void configure(WebSecurity web) {
web.ignoring().antMatchers(
// client-side JS code
"/VAADIN/**",
...
// web application manifest
"/manifest.webmanifest",
"/sw.js",
"/offline-page.html",
"/sw-runtime-resources-precache.js",
...
);
}Ignore the Service Worker Initiated Requests
Another potential Spring Security related breaking change is about using HttpSecurity.requestCache() to redirect the user to the intended page after login.
An example of using HttpSecurity.requestCache():
Source code
SecurityConfiguration.java
SecurityConfiguration.java@Override
protected void configure(HttpSecurity http) throws Exception {
...
http
// Register our CustomRequestCache, that saves unauthorized access attempts, so
// the user is redirected after login.
.requestCache().requestCache(new CustomRequestCache())
// Restrict access to our application.
.and().authorizeRequests()
// Allow all flow internal requests.
.requestMatchers(SecurityUtils::isFrameworkInternalRequest).permitAll()
...
}Now you need to ignore the service worker initiated requests, otherwise the access attempts are overridden by the service worker requests and Spring can’t redirect you to the intended page.
This can be done by inspecting the Referer header of the request.
The SecurityUtils::isFrameworkInternalRequest() can be updated as follows to also include the service worker initiated requests:
Source code
SecurityUtils.java
SecurityUtils.javastatic boolean isFrameworkInternalRequest(HttpServletRequest request) {
final String parameterValue = request
.getParameter(ApplicationConstants.REQUEST_TYPE_PARAMETER);
// Use Referer in header to check if it's a service worker
// initiated request
String referer = request.getHeader("Referer");
boolean isServiceWorkInitiated = (referer != null
&& referer.endsWith("sw.js"));
return isServiceWorkInitiated
|| parameterValue != null
&& Stream.of(RequestType.values())
.anyMatch(r -> r.getIdentifier().equals(parameterValue));
}Upgrade Steps | 19 → 20
-
Vaadin Flow doesn’t involve any API breaking changes between versions 19 and 20. See the release notes at https://github.com/vaadin/platform/releases/tag/20.0.0.
Fusion Breaking Changes
Endpoints Access is Denied by Default
Previously, endpoints (methods in classes with @Endpoint annotation) without security annotations (one of @DenyAll, @PermitAll, @RolesAllowed, @AnonymousAllowed) were accessible by all authenticated users.
To avoid inadvertent exposure of methods as endpoints, @DenyAll is now the default.
This means that you need to add explicit security annotations to the endpoints that you want to make accessible (either at the class level or the method level).
Default Spring Security Configuration
A default class for Spring Security configuration is available as VaadinWebSecurityConfigurerAdapter. Extend this class instead of the default WebSecurityConfigurerAdapter to automatically get a configuration that allows Vaadin specific requests to pass through security while requiring authorization for all other requests:
Source code
SecurityConfiguration.java
SecurityConfiguration.java@EnableWebSecurity
@Configuration
public class SecurityConfiguration extends VaadinWebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
// app's own HttpSecurity configuration as needed ...
}
@Override
protected void configure(WebSecurity web) throws Exception {
super.configure(web);
// app's own WebSecurity configuration as needed...
}
}VaadinWebSecurityConfigurerAdapter configures authentication for all routes by default.
Modify this behavior with your own followup configuration as needed.
It also bypasses framework internal and static resources (/VAADIN/**, sw.js …).
Previously, these had to be explicitly matched and ignored in the app.
VaadinWebSecurityConfigurerAdapter also configures Spring Cross-Site Request Forgery (CSRF) token for login and Fusion endpoint requests, so you no longer need to ignore Spring CSRF protection for them like before with http.csrf().ignoringAntMatchers("/login", "/connect/**");
The client-side login() method now needs the Spring CSRF token returned from a login success handler VaadinSavedRequestAwareAuthenticationSuccessHandler.
You can update your login view configuration with the setLoginView() helper, which sets up the login success handler automatically.
Source code
SecurityConfig.java
SecurityConfig.javapackage com.vaadin.demo.fusion.security.authentication;
import com.vaadin.flow.spring.security.VaadinWebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
/**
* An example code for demoing the Spring Security configuration, shouldn't affect
* the doc application itself.
*/
public class SecurityConfigDemo extends VaadinWebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
setLoginView(http, "/login");
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// Configure users and roles in memory
auth.inMemoryAuthentication().withUser("user").password("{noop}password").roles("USER");
}
@Override
public void configure(WebSecurity web) throws Exception {
super.configure(web);
web.ignoring().antMatchers("/images/**");
}
}Upgrade Steps | 20 → 21
Lit Templates Use Lit 2
Previously, Lit templates were based on LitElement 2.x and lit-html 1.x. New Lit 2.0 (which includes LitElement 3.x and lit-html 2.x) is used for Lit templates in the latest Vaadin version. Some changes are required to be able to use your existing template with Lit 2.0. See the Lit Upgrade Guide where you can find all necessary changes. Most of the necessary changes are with imports.
Use the lit package.
For example, change imports of html and LitElement from:
Source code
TypeScript
import { html, LitElement } from 'lit-element';to:
Source code
TypeScript
import { html, LitElement } from 'lit';Update decorator imports.
Decorators have been moved to a separate module.
For example, change customElement and property decorator imports from:
Source code
TypeScript
import { customElement, property } from 'lit-element';to:
Source code
TypeScript
import { customElement, property } from 'lit/decorators.js';Update directive imports from:
Source code
TypeScript
import { repeat } from 'lit-html/directives/repeat.js';to:
Source code
TypeScript
import { repeat } from 'lit/directives/repeat.js';Some Lit APIs have been renamed.
The most noticeable change is that the @internalProperty decorator has been renamed to @state.
The Vaadin Web Components No Longer Support <template>
The Vaadin Web Components no longer support <template> to render content.
Use renderer functions instead (see the "Replace Template Elements With Renderers" section).
Alternatively, you can use the @vaadin/polymer-legacy-adapter package which is created to maintain backward compatibility.
Installation
Install @vaadin/polymer-legacy-adapter as follows:
Source code
terminal
npm i @vaadin/polymer-legacy-adapter --saveImport @vaadin/polymer-legacy-adapter/template-renderer.js before any other components:
Source code
TypeScript
import '@vaadin/polymer-legacy-adapter/template-renderer.js';Deprecation Warning
By default, template-renderer.js shows a deprecation warning when <template> is used with a component.
To suppress the warning, add the suppress-template-warning attribute to the component:
Source code
HTML
<vaadin-combo-box suppress-template-warning>
<template>
Content
</template>
</vaadin-combo-box>Positive Tab Index No Longer Supported on Input Fields
Setting the tabindex attribute to a value > 0 (for example, by calling setTabIndex(10)) is no longer supported on input field components.
However, tabindex values of 0 and -1 are still supported.
Fusion Breaking Changes
Fusion Package Renaming
To give Fusion a better identity, the following Fusion packages were renamed:
-
com.vaadin.flow.server.connecttocom.vaadin.fusion -
com.vaadin.flow.server.frontend.fusiontocom.vaadin.fusion.frontend -
com.vaadin.flow.server.startup.fusiontocom.vaadin.fusion.startup
TypeScript Code Generation Nullability Change
Previously, all the Java types are generated as required in TypeScript.
Now it changes so that for any type that’s nullable in Java, it’s optional in TypeScript, that is, the value could be undefined. See the GitHub issue.
To upgrade, you can either: Update the client-side code to handle undefinable value.
Source code
TypeScript
// The address property is never undefined in Vaadin 20
person.address.street
// Use the question mark to deal with undefinable properties in Vaadin 21
person.address?.street
// The list returned from the endpoint is never undefined in Vaadin 20
const items = await endpoint.list();
// Use the double question mark to give a default value in Vaadin 21
const item = (await endpoint.list()) ?? [];Or use @Nonnull annotation on the server-side to keep the same code generation behavior as before.
Source code
Java
public class Person {
@Nonnull
private Address address;
}|
Tip
|
@Nonnull annotation@Nonnull annotations available or even your own one.
Vaadin uses case-insensitive string comparison for checking the annotation.
|
See Type Nullability for more details.
Upgrade Steps | 21 → 22
Component TypeScript APIs
Input Fields: Removed Support for Positive Tab Index
The following general changes have been made to all input field components:
-
Removed support for using positive
tabindexvalues (for example,tabindex="1") on all input field components. This doesn’t cause errors but has no effect. However, settingtabindexto0or-1is still supported. It’s recommended to ensure that input fields are in the correct order in the DOM, instead of overriding the tab order withtabindex.
Checkbox
-
A new
labelproperty was introduced to set plain text labels in client-side code, and this should be used instead of wrapping the text inside the element tags:Source code
HTML
<!-- Before --> <vaadin-checkbox>Foo</vaadin-checkbox> <!-- After --> <vaadin-checkbox label="Foo"> -
Similarly, rich (HTML) labels should be applied using the new
labelslot:Source code
HTML
<!-- Before --> <vaadin-checkbox> Foo <b>Bar</b> </vaadin-checkbox> <!-- After --> <vaadin-checkbox> <label slot="label">Foo <b>Bar</b></label> </vaadin-checkbox>
Combo Box
-
No longer extends
vaadin-text-field. -
Label, error message and the native input element are now slotted elements in light DOM instead of inside the component’s shadow DOM.
-
Dropped support for
iron-inputandpaper-inputfromvaadin-combo-box-light.
Date Picker
-
No longer extends
vaadin-text-field. -
Label, error message and the native input element are now slotted elements in light DOM instead of inside the component’s shadow DOM.
-
Removed the
i18n.calendarproperty, as it was unneeded since the toggle button is no longer announced by screen readers.
Grid
-
heightByRowsproperty renamedallRowsVisible.
Number Field
-
No longer extends
vaadin-text-field. -
Label, error message and the native input element are now slotted elements in light DOM instead of inside the component’s shadow DOM.
-
Removed
maxlength,minlengthandpatternproperties, which didn’t work anyway.
Password Field
-
Extends the updated
vaadin-text-field. See Text Field changes for details. -
Added the property
i18n.revealto provide an accessible label for the password reveal button.
Radio Button
-
New
labelproperty andlabelslot introduced to set plain-text and HTML labels, respectively:Source code
HTML
<!-- Before --> <vaadin-radio-button>Label</vaadin-radio-button> <vaadin-radio-button> <b>This</b> is a <i>rich</i> label </vaadin-radio-button> <!-- After --> <vaadin-radio-button label="Label"></vaadin-radio-button> <vaadin-radio-button> <label slot="label"> <b>This</b> is a <i>rich</i> label </label> </vaadin-radio-button>
Text Field
-
The native
<input>and<label>elements are now slotted children, instead of being inside the component’s shadow DOM. -
The
i18n.clearproperty has been removed as the clear button is no longer visible to screen readers.
Time Picker
-
No longer extends
vaadin-text-field. -
The
i18n.selectorproperty was removed as the toggle button is no longer visible to screen readers.
Upload
-
i18n.file.clearmethod renamedi18n.file.remove.
Input Fields: Removed Support for Positive Tab Index
The following general changes have been made to all input field components:
-
Removed support for using positive
tabindexvalues (for example,setTabIndex(1)) on all input field components. This doesn’t cause errors but has no effect. However, settingtabindexto0or-1is still supported. It’s recommended to ensure that input fields are in the correct order in the DOM, instead of overriding the tab order withtabindex.
Fusion Breaking Changes
Frontend npm Package
Fusion frontend code was moved from @vaadin/flow-frontend to @vaadin/fusion-frontend.
Fusion module imports need to be updated correspondingly.
For example, importing Fusion EndpointError needs to be changed as follows, from:
Source code
TypeScript
import { EndpointError } from '@vaadin/flow-frontend';to:
Source code
TypeScript
import { EndpointError } from '@vaadin/fusion-frontend';TypeScript 4.4 Default Catch Variable Type
Vaadin has changed the TypeScript dependency version to 4.4.
Starting from this version, the default catch variable type changes in TypeScript from any to unknown.
As a result, there need to be changes to the error handling code that didn’t involve instanceof guards.
For example:
Source code
TypeScript
try {
await DataEndpoint.getViewData();
} catch (error) {
console.log(error.message); // Error TS2571: Object is of type 'unknown'.
if (error instanceof Error) {
console.log(error.message); // Works.
}
}
try {
await DataEndpoint.getViewData();
} catch (error: any) {
console.log(error.message); // Works, but using `any` isn't recommended.
}See also: the TypeScript change announcement.
Positive Tab Index No Longer Supported on Input Fields
Setting the tabindex attribute to a value > 0 is no longer supported on input field components.
However, tabindex values of 0 and -1 are still supported.
Changes Affecting Custom Styling of Components
Input Field Components
These changes apply to all input field components, except Checkbox. See the sections for individual components for details and other component-specific changes.
Labels
Labels have been changed to slotted child elements.
While the [part="label"] selector still works, some derived selectors may need to be adjusted.
The :empty selector no longer works correctly to distinguish empty and non-empty labels, and should be replaced by the [has-label] attribute selector:
Source code
CSS
/* Before */
[part="label"]:not(:empty) {...}
/* After */
:host([has-label]) [part="label"] {...}
/* Or, to target the slotted element itself */
:host([has-label]) ::slotted(label) {...}Setting an input field’s label in Flow no longer generates a label attribute on the component’s root element.
Selectors using it need to be rewritten to use the has-label attribute instead:
Source code
CSS
/* Before */
:host([label]) {...}
/* After */
:host([has-label]) {...}Error Messages
Error messages have been changed to slotted child elements. While the [part="error-message"] selector still works, some derived selectors may need to be adjusted. The :empty selector no longer works correctly on these and should be replaced with attribute selectors for the appropriate states:
Source code
CSS
/* Before */
[part="error-message"]:not(:empty) {...}
/* After */
[has-error-message] [part="error-message"] {...}Required Indicators
Required indicators now have their own shadow parts, instead of being pseudo-element children of the label part:
Source code
CSS
/* Before */
[part="label"]::after {...}
/* After */
[part="required-indicator"]::after {...}Default Text Field Width
The CSS property that defines the default width of text input fields was renamed to vaadin-field-default-width:
Source code
CSS
html {
/* Before */
--vaadin-text-field-default-width: 20em;
/* After */
--vaadin-field-default-width: 20em;
}Text Field Derivatives Refactored
The following components used to be based on the Text Field component, and were mostly styled through it:
-
Combo Box
-
Date Picker
-
Number Field and Integer Field
-
Select
-
Time Picker
These have now been refactored to no longer be based on Text Field, which means that they need to be styled separately from it. See the separate upgrade guides for each of these below.
Button
Styles Inherited by Select
The Select component has been refactored to use an internal button which inherits styles applied to the Button component. To get rid of unwanted Button styles in Select, you need to either override them or scope Button styles to only apply to actual Buttons by specifying the element name in their selectors:
Source code
vaadin-button.css
vaadin-button.css/* Before */
:host {...}
:host([theme~="primary"]) {...}
/* After */
:host(vaadin-button) {...}
:host(vaadin-button[theme~="primary"]) {...}Disabled Button Styles
The styling of disabled buttons has changed from reduced opacity to a separate grayscale coloring, which may affect custom styling of buttons: secondary and tertiary buttons now use --lumo-disabled-text-color for text, while primary buttons use --lumo-contrast-30pct for background and --lumo-base-color for text.
Charts
The default colors in charts have changed in Vaadin 23 to better match the Lumo and Material themes. You can revert to the old color scheme by switching to the “classic” theme:
Source code
Java
chart.getElement().setAttribute("theme", "classic");Checkbox and Radio Button
Unlike most input field components, Checkboxes and Radio Buttons no longer have a label shadow part, so the label must be targeted as a child element:
Source code
CSS
/* Before */
[part="label"] {...}
/* After */
::slotted(label) {...}Checkbox Group
See changes common to all input field components.
Combo Box
-
See changes common to all input field components.
-
See changes to Text Field, as these also apply to Combo Box.
Styles No Longer Inherited from Text Field
This component is no longer based on Text Field, so all styles previously applied via Text Field need to be applied to it separately:
-
Using a theme folder, place the styles in
/components/vaadin-combo-box.css -
Or, in Flow, with
@CssImport(…, themeFor="vaadin-combo-box")
Overlay and List Items
The contents of vaadin-combo-box-item are now slotted child elements. This mainly affects styles applied to custom renderers:
Source code
CSS
/* Before */
[content].some-classname {...}
/* After */
::slotted(.some-classname) {...}The selection checkmarks in them have been moved to their own shadow parts:
Source code
CSS
/* Before */
:host::before {...}
/* After */
[part="checkmark"]::before {...}Miscellaneous
The vaadin-text-field-container internal wrapper has been renamed vaadin-combo-box-container. (Note: this is an internal element whose styling isn’t supported).
Confirm Dialog
Styles should now target the vaadin-confirm-dialog-overlay element instead of vaadin-confirm-dialog.
CRUD
Depending on the editor position, styles for the CRUD’s editor should now target either the vaadin-crud element itself (for aside and bottom positions) or vaadin-crud-dialog-overlay (for the overlay position), instead of vaadin-dialog-layout.
Date Picker
-
See changes common to all input field components.
-
See changes to Text Field, as these also apply to Date Picker.
Styles No Longer Inherited from Text Field
This component is no longer based on Text Field, so all styles previously applied via Text Field need to be applied to it separately:
-
Using a theme folder, place the styles in
/components/vaadin-date-picker.css -
Or, in Flow, with
@CssImport(…, themeFor="vaadin-date-picker")`
Miscellaneous
-
The
vaadin-text-field-containerinternal wrapper has been renamedvaadin-date-picker-container. (Note: this is an internal element whose styling isn’t supported). -
The calendar overlay’s week number text color has changed from
--lumo-tertiary-text-colorto--lumo-secondary-text-color.
Date Time Picker
-
See changes common to all input field components.
-
See changes to Text Field, as these also apply to Date Time Picker.
Styles No Longer Inherited from Custom Field
This component is no longer based on Custom Field, so all styles previously applied via Custom Field need to be applied to Date Time Picker separately:
-
Using a theme folder, place the styles in
/components/vaadin-date-time-picker.css -
Or, in Flow, with
@CssImport(…, themeFor="vaadin-date-time-picker")
Slotted Date Picker and Time Picker
The Date Picker and Time Picker sub-fields are now slotted children of the Date Time Picker:
Source code
CSS
/* Before */
[part="date"] {...}
[part="time"] {...}
/* After */
::slotted([slot="date-picker"]) {...}
::slotted([slot="time-picker"]) {...}The internal slot-container wrapper has been renamed slots. (Note: this is an internal element whose styling isn’t supported).
Grid
The color and opacity of inactive sort indicators were changed from --lumo-body-text-color at 0.2 opacity (0.6 on hover) to --lumo-tertiary-text-color (--lumo-body-text-color on hover) at 1.0 opacity.
Horizontal and Vertical Layout
Vertical Layout and Horizontal Layout have been refactored to use the CSS gap property for spacing between components, instead of margins.
This makes it possible to use flex-wrap to wrap the contents of these layouts without spacing conflicts.
Custom margins applied to components in these layouts are now applied in addition to the spacing, instead of overriding the spacing.
While the best approach is to refactor all custom margins applied to elements inside layouts with spacing, a quick fix is to subtract var(--lumo-space-m) from affected margins (margin-top for Vertical Layouts and margin-left for Horizontal Layouts):
Source code
CSS
/* Before */
.some-layout-child {
margin-left: 50px;
}
/* After */
.some-layout-child {
margin-left: calc(50px - var(--lumo-space-m));
}Icons
Icons are now rendered as vaadin-icon elements instead of iron-icon.
Source code
CSS
/* Before */
::slotted(iron-icon) {...}
/* After */
::slotted(vaadin-icon) {...}Number Field and Integer Field
-
See changes common to all input field components.
-
See changes to Text Field, as those also apply to Number Field and Integer Field.
Styles No Longer Inherited from Text Field
This component is no longer based on Text Field, so all styles previously applied via Text Field need to be applied to it separately:
-
Using a theme folder, place the styles in
/components/vaadin-number-field.css -
Or, in Flow, with
@CssImport(…, themeFor="vaadin-number-field")
Password Field
All styles are still inherited from Text Field, so the same changes apply to it.
Radio Button Group
-
See changes common to all input field components.
-
See Checkbox and Radio Button for changes to Radio Button.
Select
See changes common to all input field components.
Styles No Longer Inherited from Text Field
This component is no longer based on Text Field, so all styles previously applied via Text Field need to be applied to it separately:
-
Using a theme folder, place the styles in
/components/vaadin-select.css -
Or, in Flow, with
@CssImport(…, themeFor="vaadin-select")`
New List Item Element
List items are now vaadin-select-item elements instead of vaadin-item (although they extend the latter, so styles applied to vaadin-item apply to vaadin-select-item as well).
Source code
CSS
/* Before (in styles.css) */
vaadin-select-overlay vaadin-item {...}
/* After (in styles.css) */
vaadin-select-item {...}The contents of vaadin-select-item are slotted child elements. This mainly affects styles applied to custom renderers:
Source code
CSS
/* Before */
[content].some-classname {...}
/* After */
::slotted(.some-classname) {...}Selection Checkmarks
The selection checkmarks in them have been moved to their own shadow parts:
Source code
CSS
/* Before */
:host::before {...}
/* After */
[part="checkmark"]::before {...}Value Displayed in Field
The value displayed in the field uses the new item element too, and is now a child of a new vaadin-select-value-button internal component, and is easiest to access as a regular child element of Select:
Source code
CSS
/* Before (in vaadin-item) */
[part="value"] vaadin-item {...}
/* After (in styles.css) */
vaadin-select vaadin-select-item {...}Placeholder Text
The value placeholder text needs to be targeted a bit differently from other similar fields:
Source code
CSS
/* Before */
[part="value"]:placeholder-shown {...}
/* After */
::slotted([placeholder]) {...}Tabs
The color of inactive tabs has been changed from --lumo-contrast-60pct to --lumo-secondary-text-color.
Text Area
See changes common to all input field components.
Slotted Native Input Element
The native <textarea> element is now a slotted child element, and the value shadow part has been removed:
Source code
CSS
/* Before */
[part="value"] {...}
/* After */
::slotted(textarea) {...}This also affects selectors for the placeholder text:
Source code
CSS
/* Before */
[part="value"]::placeholder {...}
/* or */
[part="value"]:placeholder-shown {...}
/* After */
::slotted(textarea:placeholder-shown) {...}Text Field
See changes common to all input field components.
Other Text Input Components No Longer Based on Text Field
The following components that used to be based on Text Field are no longer so, and need to be styled separately instead of inheriting styles from Text Field:
-
Combo Box
-
Date Picker
-
Number Field
-
Select
-
Time Picker
However, the same structural changes were made to these as to Text Field, so the following changes and corresponding instructions apply to them as well.
Slotted Native Input Element
The native <input> element is now a slotted child element, and the value shadow part has been removed:
Source code
CSS
/* Before */
[part="value"] {...}
/* After */
::slotted(input) {...}This also affects selectors for the placeholder text:
Source code
CSS
/* Before */
[part="value"]::placeholder {...}
/* or */
[part="value"]:placeholder-shown {...}
/* After */
::slotted(input:placeholder-shown) {...}Placeholder Text Color
Placeholder text now uses the --lumo-secondary-text-color color property, instead of --lumo-body-text-color with 0.5 opacity.
Time Picker
-
See changes common to all input field components.
-
See changes to Text Field, as these also apply to Number Field and Integer Field.
Styles No Longer Inherited from Text Field
This component is no longer based on Text Field, so all styles previously applied via Text Field need to be applied to it separately:
-
Using a theme folder, place the styles in
/components/vaadin-time-picker.css -
Or, in Flow, with
@CssImport(…, themeFor="vaadin-time-picker")
Upload
The clear-button part was renamed remove-button:
Source code
CSS
/* Before */
[part="clear-button"] {...}
/* After */
[part="remove-button"] {...}Upgrade Steps | 22 → 23
npm as the Default Frontend Package Manager
Starting from Vaadin 23, npm is used as the default frontend package manager, since the performance of npm has been improved and it’s possible to lock dependency versions with the npm overrides feature.
pnpm is still supported.
To continue using pnpm, set the pnpm.enable flag to true.
Flow Breaking Changes
-
Java version requirement changes from Java 8 to Java 11
For Maven update the java.version
Source code
XML
<properties> <java.version>11</java.version> </properties>or compiler.source and compiler.target
Source code
XML
<properties> <maven.compiler.source>11</maven.compiler.source> <maven.compiler.target>11</maven.compiler.target> </properties> -
For Java 9+
maven-failsafe-pluginrequires jaxb-impl to be addedThe dependency can be added directly in the plugin definition as:
Source code
XML
<plugin> <artifactId>maven-failsafe-plugin</artifactId> <dependencies> <dependency> <groupId>com.sun.xml.bind</groupId> <artifactId>jaxb-impl</artifactId> <version>${jaxb.version}</version> </dependency> </dependencies> </plugin> -
Frontend package manager changes from pnpm to npm
The default package manager is now npm, but if using a version older than 8.3 it’s recommended to use pnpm instead.
To keep using pnpm the configuration pnpm.enable should be set.
Source code
Maven<plugin> <groupId>com.vaadin</groupId> <artifactId>flow-maven-plugin</artifactId> <configuration> <pnpmEnable>true</pnpmEnable> </configuration> </plugin>Source code
Gradlevaadin { pnpmEnable = true }Or using the system property
vaadin.pnpm.enable=trueNoteRunning npmwithout apackage-lock.jsonis slow for the initial installation. A project that comes frompnpmdoesn’t have annpmpackage-lock.json, as it usespnpm-lock.yaml. -
Charts CSS styling mode no longer requires importing and including the default charts theme, so these should be removed.
Source code
Java
/* Before */ @JsModule("@vaadin/vaadin-charts/theme/vaadin-chart-default-theme") @CssImport(value = "my-chart-styles.css", themeFor = "vaadin-chart", include = "vaadin-chart-default-theme") /* After */ @CssImport(value = "my-chart-styles.css", themeFor = "vaadin-chart")
Changes
-
Recommended minimum version of npm is v8.3
This is to have the support for overrides to lock transitive dependencies versions.
-
When the global node isn’t compatible, the version in
~/.vaadinis used.If a version doesn’t exist or is too old it is automatically downloaded and installed.
Hilla as a Standalone Platform
Fusion used to be part of the Vaadin platform, now it’s separated from Vaadin and packaged as a standalone platform called Hilla. Hilla and Vaadin work seamlessly together, as long as the versions match. They share the same minor and patch versions; the difference is that Vaadin has 23 as the major version, while Hilla has 1.
Use Hilla Dependency Instead of Vaadin
For a pure Fusion application, you can update the Vaadin dependency and related artifacts to Hilla.
The benefit is that some unnecessary dependencies are excluded, for example, the server-side Flow components.
Here is an example of pom.xml file updates:
Source code
XML
<!-- use hilla version instead of vaadin -->
<hilla.version>1.0.0</hilla.version>
<!-- use hilla bom instead of vaadin -->
<dependency>
<groupId>dev.hilla</groupId>
<artifactId>hilla-bom</artifactId>
<version>${hilla.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- use hilla dependency instead of vaadin -->
<dependency>
<groupId>dev.hilla</groupId>
<artifactId>hilla</artifactId>
</dependency>
<!-- use hilla-spring-boot-starter instead of vaadin-spring-boot-starter -->
<dependency>
<groupId>dev.hilla</groupId>
<artifactId>hilla-spring-boot-starter</artifactId>
</dependency>
<!-- use hilla-maven-plugin instead of vaadin-maven-plugin -->
<groupId>dev.hilla</groupId>
<artifactId>hilla-maven-plugin</artifactId>
<version>${hilla.version}</version>There’s no hilla-core dependency; both vaadin and vaadin-core should be replaced with hilla.
Flow-Hilla Hybrid Projects
If a Flow application needs the Hilla features, such as Endpoint, it can be updated to also include the hilla dependency in the pom.xml file.
Here is an example of how to do that:
Source code
XML
<vaadin.version>23.0.0</vaadin.version>
<!-- add the hilla version -->
<hilla.version>1.0.0</hilla.version>
<dependency>
<groupId>com.vaadin</groupId>
<artifactId>vaadin-bom</artifactId>
<version>${vaadin.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- add the hilla bom -->
<dependency>
<groupId>dev.hilla</groupId>
<artifactId>hilla-bom</artifactId>
<version>${hilla.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.vaadin</groupId>
<artifactId>vaadin</artifactId>
</dependency>
<!-- add the hilla dependency -->
<dependency>
<groupId>dev.hilla</groupId>
<artifactId>hilla</artifactId>
</dependency>Java Package Renaming
The com.vaadin.fusion package was renamed to dev.hilla, so the Java imports need to be updated accordingly.
For example, importing Endpoint needs to be changed as follows, from:
Source code
Java
import com.vaadin.fusion.Endpoint;to:
Source code
Java
import dev.hilla.Endpoint;Front-End npm Package Renaming
The front-end code was moved from @vaadin/flow-frontend to @vaadin/fusion-frontend, and from @vaadin/form to @hilla/form.
The module imports need to be updated correspondingly.
For example, importing EndpointError, Binder and field need to be changed as follows, from:
Source code
TypeScript
import { EndpointError } from '@vaadin/fusion-frontend';
import { Binder, field } from '@vaadin/form';to:
Source code
TypeScript
import { EndpointError } from '@hilla/frontend';
import { Binder, field } from '@hilla/form';Add Hilla Package to whitelisted-packages List
Make sure that dev.hilla is added to the vaadin.whitelisted-packages property inside application.properties file.
For example, the property should be changed to look something as follows:
Source code
src/main/java/resources/application.properties
src/main/java/resources/application.propertiesvaadin.whitelisted-packages = com.vaadin,org.vaadin,com.example.application,dev.hilla