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_modules
folder and either lock file:package-lock.json
(withnpm
) orpnpm-lock.yaml
(withpnpm
). -
Edit the
pom.xml
file 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:
<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:
@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
Element
are replaced with similar API inDomListenerRegistration
:getSynchronizedPropertyEvents
,getSynchronizedProperties
,removeSynchronizedPropertyEvent
,removeSynchronizedProperty
,addSynchronizedPropertyEvent
,addSynchronizedProperty
,synchronizeProperty
. -
JavaScript execution APIs
executeJavaScript
andcallFunction
inElement
andPage
are replaced with similarly named methods that give access to the return valueexecuteJs
andcallJsFunction
: -
Miscellaneous
Element
methods: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)
inBeforeEvent
are replaced withBeforeEvent(NavigationEvent, Class, List)
andBeforeEvent(Router, NavigationTrigger, Location, Class, UI, List)
-
Methods
getUrl()
,getUrlBase()
andgetRoutes()
inRouter
are replaced with methodsgetUrl()
,getUrlBase()
andgetAvailableRoutes()
inRouterConfiguration
. Theresolve()
method inRouter
is replaced with theresolve()
method inRouteUtil
. ThegetRoutesByParent()
method inRouter
is removed and has no replacement. -
ServletHelper
is replaced withHandlerHelper
-
ExecutionCanceler
is replaced withPendingJavaScriptResult
-
The
getBodyAttributes
method inAbstractTheme
,Lumo
andMaterial
is replaced withgetHtmlAttributes
-
The
removeDataGenerator
method inHasDataGenerators
andCompositeDataGenerator
is removed in favor of using the registration returned fromaddDataGenerator(DataGenerator)
-
The methods
preventsDefault
andstopsPropagation
inShortcutRegistration
are replaced withisBrowserDefaultAllowed ` and `isEventPropagationAllowed
-
The
safeEscapeForHtml
method inVaadinServlet
is removed in favor of usingorg.jsoup.nodes.Entities#escape(String)
-
The static method
getInstance
inApplicationRouteRegistry
is removed in favor of the instance method. -
The protected instance method
getApplicationUrl
fromVaadinServlet
is 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.html
page includes the code and configuration needed to start the Flow client engine and link the browser page to the server-sideUI
instance. -
In Vaadin 15+ with client-side bootstrapping the
index.html
page includes only the basic HTML markup and links to the TypeScript UI code. If you have client-side/Hilla views, theUI
isn’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:
Meta.class, PWA.class, Inline.class, Viewport.class, BodySize.class, Push.class
Replace Obsolete APIs
A New API for Binding Items to Components:
-
HasDataProvider
andHasItems
are now replaced by the newHasListDataView
,HasLazyDataView
andHasDataView
interfaces inGrid
,Select
andCheckBoxGroup
. 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
HasItemsAndComponents
interface has been replaced byHasItemComponents
to support the Data View API in in-memory binding components. -
HasHierarchicalDataProvider
no longer hassetItems()
overloads forCollection
,Stream
andArray
.
URL Parameters Template Feature
-
BeforeEvent
has a bunch of new methods for forwarding, rerouting and getting the parameters. Some methods are now deprecated or removed. -
The
RouteRegistry
andSessionRouteRegistry
interfaces are now supplemented with new methods and deprecate getters for route layouts. -
com.vaadin.flow.server.startup.RouteTarget
has 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
LitTemplate
is recommended over the deprecatedPolymerTemplate
to 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
@Id
mapping components. This applies toPolymerTemplate
, too. More information on the template support is available in this blog post.
Flow Breaking Changes
-
AppShellRegistry
methodgetTitle()
is removed It was broken and couldn’t work. Instead, if needed, usegetUI().getUIInternals().getAppShellTitle()
. -
Having the
@Theme
annotation on Flow views or router layouts is no longer allowed. The annotation should be onAppShellConfigurator
instead. This is now consistent with the@PWA
annotation. It’s also cleaner, since you can only have one@Theme
per application. -
AbstractListDataView
now 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
value
property ofBinderNode
now has optionallyundefined
type 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:
public 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:
@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:
@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()
:
@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:
static 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:
@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.
package 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:
import { html, LitElement } from 'lit-element';
to:
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:
import { customElement, property } from 'lit-element';
to:
import { customElement, property } from 'lit/decorators.js';
Update directive imports from:
import { repeat } from 'lit-html/directives/repeat.js';
to:
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:
npm i @vaadin/polymer-legacy-adapter --save
Import @vaadin/polymer-legacy-adapter/template-renderer.js
before any other components:
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:
<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.connect
tocom.vaadin.fusion
-
com.vaadin.flow.server.frontend.fusion
tocom.vaadin.fusion.frontend
-
com.vaadin.flow.server.startup.fusion
tocom.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.
// 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.
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
tabindex
values (for example,tabindex="1"
) on all input field components. This doesn’t cause errors but has no effect. However, settingtabindex
to0
or-1
is 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
label
property 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:<!-- Before --> <vaadin-checkbox>Foo</vaadin-checkbox> <!-- After --> <vaadin-checkbox label="Foo">
-
Similarly, rich (HTML) labels should be applied using the new
label
slot:<!-- 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-input
andpaper-input
fromvaadin-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.calendar
property, as it was unneeded since the toggle button is no longer announced by screen readers.
Grid
-
heightByRows
property 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
,minlength
andpattern
properties, which didn’t work anyway.
Password Field
-
Extends the updated
vaadin-text-field
. See Text Field changes for details. -
Added the property
i18n.reveal
to provide an accessible label for the password reveal button.
Radio Button
-
New
label
property andlabel
slot introduced to set plain-text and HTML labels, respectively:<!-- 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.clear
property has been removed as the clear button is no longer visible to screen readers.
Time Picker
-
No longer extends
vaadin-text-field
. -
The
i18n.selector
property was removed as the toggle button is no longer visible to screen readers.
Upload
-
i18n.file.clear
method 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
tabindex
values (for example,setTabIndex(1)
) on all input field components. This doesn’t cause errors but has no effect. However, settingtabindex
to0
or-1
is 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:
import { EndpointError } from '@vaadin/flow-frontend';
to:
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:
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:
/* 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:
/* 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:
/* 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:
/* 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
:
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:
/* 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:
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:
/* 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:
/* Before */
[content].some-classname {...}
/* After */
::slotted(.some-classname) {...}
The selection checkmarks in them have been moved to their own shadow parts:
/* 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-container
internal 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-color
to--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:
/* 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):
/* 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
.
/* 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).
/* 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:
/* Before */
[content].some-classname {...}
/* After */
::slotted(.some-classname) {...}
Selection Checkmarks
The selection checkmarks in them have been moved to their own shadow parts:
/* 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:
/* 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:
/* 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:
/* Before */
[part="value"] {...}
/* After */
::slotted(textarea) {...}
This also affects selectors for the placeholder text:
/* 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:
/* Before */
[part="value"] {...}
/* After */
::slotted(input) {...}
This also affects selectors for the placeholder text:
/* 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
:
/* 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
<properties> <java.version>11</java.version> </properties>
or compiler.source and compiler.target
<properties> <maven.compiler.source>11</maven.compiler.source> <maven.compiler.target>11</maven.compiler.target> </properties>
-
For Java 9+
maven-failsafe-plugin
requires jaxb-impl to be addedThe dependency can be added directly in the plugin definition as:
<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.
<plugin> <groupId>com.vaadin</groupId> <artifactId>flow-maven-plugin</artifactId> <configuration> <pnpmEnable>true</pnpmEnable> </configuration> </plugin>
vaadin { pnpmEnable = true }
Or using the system property
vaadin.pnpm.enable=true
NoteRunning npm
without apackage-lock.json
is slow for the initial installation. A project that comes frompnpm
doesn’t have annpm
package-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.
/* 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
~/.vaadin
is 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:
<!-- 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:
<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:
import com.vaadin.fusion.Endpoint;
to:
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:
import { EndpointError } from '@vaadin/fusion-frontend';
import { Binder, field } from '@vaadin/form';
to:
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:
vaadin.whitelisted-packages = com.vaadin,org.vaadin,com.example.application,dev.hilla