Changes since 25.2.0-beta1
Breaking changes
-
NativeLabel.setFor() lazily resolves and auto-generates IDs
Commit · Pull request · IssuesetFor(Component)now resolves the component's ID lazily at sync time instead of requiring it immediately, and auto-generates one if the component still has no ID. Developers no longer need to manually assign IDs to components used withsetFor().
New features
-
Support not having a project-specific index.html
Commit · Pull requestThe Vaadin-generated
index.htmlis again placed infrontend/generated/instead offrontend/. A user-providedfrontend/index.htmlstill overrides the default, so having anindex.htmlin the project is optional again, as in Vaadin 14. -
Add HasAriaRole interface
Commit · Pull requestAdds a shared
HasAriaRolemixin interface so components like Card, Badge, Dialog, and Popover can share a single contract instead of duplicating logic. It sits next toHasAriaLabelincom.vaadin.flow.componentand follows the same pattern: attribute-based storage,nullclears the attribute, and the getter returns anOptional. -
Allow setting frontend build toggles via system properties
Commit · Pull requestSeveral
build-frontendtoggles could previously only be set through a POM<configuration>block. Apropertyattribute is added togenerateBundle,runNpmInstall,generateEmbeddableWebComponents,optimizeBundle, andeagerServerLoadso they can be overridden at runtime, e.g.-Dvaadin.generateBundle=false. -
Warn when an add-on uses the legacy META-INF/resources/frontend layout
Commit · Pull requestTaskCopyFrontendFilesstill scans the deprecatedMETA-INF/resources/frontend/for backwards compatibility, but now emits a once-per-jar/dir warning recommending the split layout: bundle sources for@JsModule/@CssImportunderMETA-INF/frontend/, and runtime resources for@StyleSheet/@JavaScriptunderMETA-INF/resources/. -
Support custom timeout for DevTools license download
Commit · Pull request · IssueThe DevTools license-checker waited a fixed 60 seconds for the asynchronous license download, which is too short for first-time users who must still register a Vaadin account. Callers of
downloadLicensecan now pass an optional timeout; when omitted, the previous default is kept. -
Add RouterState.isNavigationPending()
Commit · Pull request · IssueAdds
RouterState.isNavigationPending()so user code can detect the pre-navigation state without an NPE. -
Fail loudly when a trigger is created without an action
Commit · Pull requestA
Triggerthat is never armed with an action does nothing on the client, which is almost always a forgotten terminal binding call (e.g.Clipboard.onClick(button)with no followingwriteText(...)). This is now detected in theTriggerbase class viabeforeClientResponse, throwing anIllegalStateExceptionif no action was committed.Trigger.triggersWhenAttached(target, supplier)is added so a binding that legitimately defers wiring until a target attaches is not mistaken for a forgotten one. -
Expose page title resolution as public API
Commit · Pull requestAdds
Router.resolvePageTitlefor resolving the page title of a navigation target without instantiating it, applying the same dynamic / default / staticPageTitlechain used during navigation.RouteUtil.resolvePageTitleis deprecated and now delegates toRouter. -
Allow custom actions and triggers to consume trigger inputs
Commit · Pull requestAction.Input#toJsis widened topublicso anActionimplemented outside the internal trigger package can render anInputreceived as a parameter.HandlerInputand its constructor are also made public so custom trigger families can reuse the canonical implementation instead of declaring anonymous subclasses. -
Add Screen Orientation API support to Page
Commit · Pull requestExposes the browser Screen Orientation API through
Pagemethods, providing a read-only signal for tracking orientation changes and methods to lock/unlock screen orientation for tablet and mobile apps. -
Add Web Share API support
Commit · Pull requestAdds a
WebSharefacade for the browser's Web Share API:WebShare.onClick(button).share(ShareContent.create().title(...).text(...).url(...))opens the native share sheet on click, optionally reporting the outcome throughonShared/onErrorcallbacks.ShareContentslots accept either string literals orHasValuecomponents, andWebShare.supportSignal()exposes feature detection as a read-only signal. -
Set X-Frame-Options header by default
Commit · Pull request · IssueThe
X-Frame-Optionsresponse header is now sent with a default value ofSAMEORIGINso browsers opt in to clickjacking protection out of the box. It is configurable through the newframeOptionsinit parameter (DeploymentConfiguration#getFrameOptions); an empty value disables the header for apps meant to be embedded in a frame. -
Validate URL schemes in Anchor, IFrame and Page#open
Commit · Pull requestRe-introduces URL-scheme validation for link and navigation sinks using application-wide configuration plus a per-instance opt-out. Safe schemes are read from the new
com.vaadin.safeUrlSchemes(InitParameters.URL_SAFE_SCHEMES) property, defaulting tohttp,https,mailto,tel, andftp, so script-capable schemes such asjavascriptanddataare rejected. Setting the property to*marks every scheme safe. For trusted, hard-coded URLs, each sink offers an unsafe variant:Anchor#setUnsafeHref,IFrame#setUnsafeSrc, andPage#openUnsafe. -
Add UI.triggerAfter for deferred server-side callbacks
Commit · Pull requestAdds
UI.triggerAfter(Duration, SerializableRunnable), which runs a task on the server once the given delay has elapsed. The delay is measured by the browser via a one-shot client timer that makes a normal round trip when it elapses, so a single deferred event can be handled without enabling push. The returnedRegistrationcancels the client timer when removed. -
Add Clipboard.onFilePaste for server-side file paste handling
Commit · Pull requestPastes that carry files (screenshots, files copied from a file manager) flow through the supplied
UploadHandler— one POST per file, matching vaadin-upload's wire format.PasteFileHandleroffersinMemory(consumer), which delivers each file as aPasteFile, andsession(...), which builds anonStart/onFile/onCompletelistener that knows when a whole paste has finished.onFilePasteis independent ofonPaste; both fire on the same gesture when registered. -
Add route hierarchy with dynamic titles
Commit · Pull requestIntroduces an instance-free mechanism for resolving page titles and logical route hierarchies without instantiating navigation target components. New annotations, interfaces, and APIs let routes declare a
PageTitleGeneratorand a static or resolver-based logical parent, enabling dynamic titles and hierarchical navigation aids such as breadcrumbs and menus. -
Add Safelist overloads to Html component
Commit · Pull request · IssueAdds
Safelistoverloads to theHtmlcomponent, giving control over which HTML elements and attributes are permitted in the parsed content. -
Add Clipboard.onPaste for server-side paste handling
Commit · Pull requestAdds
Clipboard.onPaste(Component, listener)(and aPasteOptionsoverload) that forwards the browser's native paste event to a server-side listener as aPasteEventcarryingtext/plain,text/html, the source component, and the closest Flow-tracked target element. Pass any component to scope the listener to it and its descendants, or theUIfor UI-wide scope. By default, pastes targeting input/textarea/contenteditable elements are filtered out client-side;PasteOptions.includingInputFields()disables that filter. -
Public read API on ClipboardBinding
Commit · Pull requestClipboard.onClick(button).read(onPayload, onError)— and thereadText/readHtmlconvenience variants — make the clipboard read side reachable from the same binding entry point as the write side.ClipboardPayloadmoves to the publicclipboardpackage so it can appear in these method signatures. -
OpenInNewTabAction for the action trigger framework
Commit · Pull requestAdds
OpenInNewTabActionto the internal trigger system for opening URLs in a new tab or window in response to user actions. Dangerousjavascript:URLs are blocked both server- and client-side, and popup features are configurable. -
DownloadAction for the action trigger framework
Commit · Pull requestAdds a server-side
DownloadActionfor triggering browser downloads from static URLs, server-generated streams, or client-resolved values, with optional filename suggestions. The client-side helper synthesizes and clicks an anchor element and is exposed underwindow.Vaadin.Flow.download.start. -
Add image/png to the Clipboard write API
Commit · Pull requestLets an app copy an image to the system clipboard as
image/pngwhen a trigger fires, alongside the existingtext/plainandtext/htmlslots. Two image sources are supported: an<img>-rooted component already on the page, or aDownloadHandlerthat serves bytes from the server. Image-only and multi-format writes (text + HTML + image in oneClipboardItem) are both supported via the newClipboardBinding.writeImage(...)methods andClipboardContent.image(...). -
RPC invocation listener support
Commit · Pull requestEnables listening to RPC invocations.
-
Add session lock request, acquire, release events
Commit · Pull requestEnables listening to session lock request, acquire, and release events.
-
Screen Wake Lock API on Page
Commit · Pull requestAdds a per-UI
WakeLockfacade reached throughPage#getWakeLock(), exposingrequest(),release(), and an active-stateSignal<Boolean>. The client transparently re-acquires the lock onvisibilitychange, so a singlerequest()covers the lifetime of a view; failures (insecure context, unsupported browser, denied) leave the active signalfalse. -
SizeTrigger — a trigger that fires on element resize
Commit · Pull requestAdds a
SizeTriggerthat wires the browser'sResizeObserverinto the trigger framework, exposingwidth(),height(), andsize()inputs. Combined withSetSignalAction, this provides a purely server-side equivalent of an element size signal. -
Add Fullscreen API wrapping the browser Fullscreen API
Commit · Pull requestAdds
Component.requestFullscreen()(using a wrapper approach that handles Vaadin theming and overlay components correctly), along withPage.requestFullscreen(),Page.exitFullscreen(), andPage.fullscreenSignal()for reactive observation of the fullscreen state. -
Add virtual-aware component tree traversal helpers
Commit · Pull requestAdds
ComponentUtil.getAllChildrenandComponentUtil.streamDescendants. UnlikeComponent.getChildren, these include components attached as virtual children (slotted helpers, overlays attached to the UI, the client-side routing wrapper), so tools needing a complete component tree no longer have to reach into internal APIs. -
SignalInput — read a server-side Signal at trigger fire time
Commit · Pull requestAdds
SignalInput<T>(Component owner, Signal<T> signal)so actions can use a server-side signal as their value source at trigger fire time without first projecting it onto a DOM property. -
CallbackAction + SetSignalAction — trigger actions for server-side callbacks
Commit · Pull requestCallbackAction<T>forwards a value from a trigger's handler scope back to the server, decodes it asT, and hands it to aSerializableConsumer<T>on the UI thread, bridging any client-side trigger into arbitrary server-side state.SetSignalActionis a thin named subclass for the commonsignal::setcase.
Fixes
-
Keep component fullscreen working when the target is the view root
Commit · Pull requestrequestComponentFullscreenthrew "Cannot read properties of undefined" when the fullscreened component was the wrapper's direct child (the route view root), because the inserted placeholder comment became the wrapper's first node. The view root is now captured viafirstElementChildbefore mutating the DOM, and hiding is skipped when the fullscreened component is itself the view root. -
Move internal frontend sources out of deprecated location
Commit · Pull request · Issueflow-reactandflow-dndshipped their@JsModulebundle sources (ReactRouterOutletElement.tsxanddndConnector.js) under the deprecatedMETA-INF/resources/frontend/location, triggering a per-jar deprecation warning. They are moved toMETA-INF/frontend/, withFrontendDependenciesfalling back to the legacy location for older add-on jars. -
Do not keep vaadin.overrides
Commit · Pull request · IssueWhen setting overrides, Vaadin versions are removed and re-added from the platform,
$VALUEentries with no dependency or devDependency are cleared, and dependencies/devDependencies are added as$overrides. User overrides should live in dependencies/devDependencies. -
Allow UI polling while a modal component is open
Commit · Pull request · IssuePoll listeners registered through
PollNotifier.addPollListenerare now registered withallowInert, so they keep firing even when a modal component makes the UI inert. UI polling is a global, UI-level feature and should not be blocked by a modality curtain; previously, opening a modal dialog dropped poll events for as long as the modal stayed open. -
Ignore empty entries when parsing postinstall package lists
Commit · Pull request · IssueSplitting an empty configuration value on "," yields a single empty string rather than an empty array, which caused
TaskRunNpmInstallto attempt a postinstall for a package with an empty name. The additional and exclude postinstall package properties are now parsed through a shared helper that trims entries and drops blank ones, so an unset property yields an empty list. -
Keep project version data in telemetry after a clear
Commit · Pull requestThe dev-mode usage statistics file is shared by all dev servers on a machine; after a successful upload,
StatisticsSendercleared the whole projects array, wiping the data of other still-running dev servers. Project identity data (flowVersion,vaadinVersion,hillaVersion,sourceId) is now re-asserted whenever a running session writes project data and the entry is missing it, so reports always include complete version information. -
Write frontend build files into build dir when it is outside project dir
Commit · Pull request · IssueWhen the build dir is relocated outside the project dir,
vaadinPrepareFrontendwrotevaadin-dev-server-settings.jsonand the dev-bundle output under the source tree.buildFolder()is now always relative toprojectDir. -
Cancel pending validation effect listener on binding removal
Commit · Pull request · IssueBinding a not-yet-attached field schedules the internal validation signal effect via a component attach listener. That listener registration was not tracked, so
unbind()could not cancel it, leaving a stale listener that fired on a later attach and threw an NPE ("This binding is already unbound"). The attach listener registration is now stored and removed inunbind(). -
Support the configuration cache when packaging the production jar
Commit · Pull request · IssueThe production-mode token-restore action was added as a
Jar.doFirst {}whose lambda captured the wholeProject, which can't be serialized for the configuration cache. It now captures thevaadinBuildFrontendTokenservice provider instead. -
Preserve dev-server generated frontend files during prepare-frontend
Commit · Pull requestA standalone prepare-frontend run cleaned the frontend generated folder by deleting any file it did not itself produce, removing files generated only by a full generation run (
index.tsx,vaadin-react.tsx,layouts.json,flow/ReactAdapter.tsx,vite-devmode.ts) out from under a running app. A generation run now records the files it produces in a manifest; the prepare-frontend cleanup reads that manifest and preserves these files instead of deleting them. -
Improve shared signal transaction error message
Commit · Pull requestClarifies the error shown when updating multiple shared signals in a transaction, explaining the restriction with cluster context.
-
Fire cancelable event on license download instead of forcing reload
Commit · Pull request · IssueDevTools reloaded the page when a license was downloaded, which prevented consumers (such as Copilot) from resuming an ongoing operation. A cancelable
vaadin-license-download-completedevent is now dispatched on the document; if no listener callspreventDefault(), the previous reload behavior is kept as the default. -
Send browser details as plain query parameters during v-r=init
Commit · Pull request · IssueThe initial
v-r=initbootstrap request appended browser details as a single JSON-encodedv-browserDetailsquery parameter, whose percent-encoded escapes (%7B,%22,%3A, ...) some firewalls/WAFs flag and block, failing the app on the first page load. Browser details are now appended as individual, unwrappedv-*query parameters (e.g.&v-sw=1641&v-tzid=Europe%2FBerlin), which contain no JSON braces or quotes. -
Write generated frontend files atomically
Commit · Pull requestGenerated frontend files were written via
Files.writeString, which truncates and rewrites in place, so a file watcher such as Vite's could read an empty or partial file and crash the dev server.FileIOUtils.writeIfChangednow writes to a temp file in the same directory and moves it over the target atomically (falling back to a regular replace where atomic moves are unsupported). -
Read Vaadin version from vaadin-core-internal pom.properties
Commit · Pull requestPlatform.getVaadinVersion()now reads fromvaadin-core-internal/pom.propertiesinstead of the hardcodedvaadin-core/pom.propertiespath.vaadin-corealways depends onvaadin-core-internal, so the version is always available on the classpath. -
Unpack prod bundle on Windows mapped network drives
Commit · Pull request · IssueThe Zip Slip guard in
CompressUtil.newFilecanonicalized the target dir and the not-yet-created entry separately; on mapped/substdrivesgetCanonicalPath()returns inconsistent forms, so legitimate entries were rejected. The destination is now canonicalized once and entries are resolved lexically, checking containment withPath.startsWith. -
Declare signal class tokens as
Class<@NonNull T>
Commit · Pull requestNullAway 0.13.2+ rejects passing
String.classto a signal constructor takingClass<T>for a@Nullableelement type, sinceClass<T>is invariant. The type-token parameter and backing field are now declared asClass<@NonNull T>, letting callers pass a plain class literal for a nullable element type with no cast. -
Omit feature flag updater script when no flags are enabled
Commit · Pull request · IssueThe feature-flag bootstrap script was always written into
index.html, even when no flags were enabled, shipping a redundant registration in every default production app. It is now omitted when no feature flags are enabled. -
Avoid stale and duplicate observers on concurrent Effect revalidation
Commit · Pull requestEffect.revalidate()registers signal-tree observers without holding the Effect monitor (to avoid the ABBA deadlock fixed in #24362), so overlapping revalidation/invalidation/activation attempts could each add a generation of observers, leaving duplicate or stale listeners. Agenerationcounter bumped under the Effect monitor now lets each attempt install its observers only if it is still the latest; stale attempts remove the observers they created. -
Revert "fix: Add Url validation in Anchor and Page#open (#24371)"
Commit · Pull requestReverts commit a35f9be. The validation is re-introduced in a thread-safe form by #24539.
-
Add Url validation in Anchor and Page#open
Commit · Pull requestAdds URL validation in
AnchorandPage#open. Superseded — reverted in #24502 and re-introduced via #24539. -
iOS home screen app height
Commit · Pull request · IssueThe bootstrap page now ensures the app covers the entire viewport height on iOS when opened as a standalone / home-screen app.
-
Avoid false infinite loop detection when a cached signal self-updates
Commit · Pull request · IssueWhen an effect reads a cached signal that detects its value is stale, the cached signal recomputes and submits an update, which was incorrectly flagged as an infinite loop even though it is lazy evaluation during a read, not a write loop. A thread-local flag now marks the read-triggered update context so infinite-loop detection is skipped for it.