Preserving the State on Refresh
When a URL is entered in the browser, Vaadin’s routing subsystem resolves it into a view component by inspecting @Route
class annotations. When a matching class is found, a new instance is created by default. This also happens when the user refreshes the page in the same browser tab.
Occasionally, you may want to keep the state of the view between these refreshes. For example, if the view contains many data entry components, and the user is likely to refresh the page (intentionally or unintentionally) before the data is persisted in the backend. By preserving the view, you ensure the entries are not lost and provide a better UX. Another use case is supporting browser tab-specific "sessions" as an alternative to the standard cookie-based session.
The @PreserveOnRefresh
annotation instructs Vaadin to re-use the view component of a route whenever the route is reloaded in the same browser tab. The routed component instance is then the same server-side object that was created in the first request, with all related to its state preserved (i.e., member fields, subcomponent hierarchy, and so on).
Preserving the State of a Component
To make a single-view component preserve its content on refresh, simply add the @PreserveOnRefresh
annotation to the class.
Example: Adding the @PreserveOnRefresh
annotation to the PreservedView
class.
@Route("myview")
@PreserveOnRefresh
public class PreservedView extends VerticalLayout {
public PreservedView() {
add(new TextField("Content will be preserved"));
// ...
}
}
If the view component has a router layout (via the layout
parameter of the @Route
annotation), the router layout is also preserved on refresh. As an alternative, you can add the @PreserveOnRefresh
annotation to a class that implements RouterLayout
.
Example: Adding the @PreserveOnRefresh
annotation to an implementation of RouterLayout
.
@PreserveOnRefresh
public class PreservedLayout extends FlexLayout
implements RouterLayout {
public PreservedLayout() {
// ...
}
}
The PreservedLayout
instance itself, as well as any view laid out inside it, is preserved on refresh.
Any elements that are not direct children of the view component, such as notifications and dialogs, are also preserved. This means that if your @PreserveOnRefresh
annotated-view class opens a dialog, in which the user makes edits and then refreshes, the dialog remains visible in its edited state.
Preconditions and Limitations
Using the @PreserveOnRefresh
annotation has the following conditions or limitations:
-
The annotation must be placed in a component class that is a route target (typically annotated with
@Route
) or on a component that implementsRouterLayout
. -
The annotation does not support partial preserving. You cannot preserve only some components on the route chain. If the annotation is present on any component in the chain, the entire chain is preserved.
-
The component is persisted only when reloaded in the same browser tab (the
window.name
client-side property is used to identify the tab), and only if the URL stays the same (visiting another route or changing a URL parameter discards the component state permanently). -
Vaadin 10 and later does not preserve the
UI
instance between refreshes. The view is detached from its previousUI
and then attached to a freshUI
instance on refresh. This also means that any data stored in theUI
instance will be lost on refresh. Data should be stored for example in the component that has the@PreserveOnRefresh
annotation. -
The
AttachEvent
andDetachEvent
events are also generated when a preserved component is moved to a newUI
. This means, for instance, that your view component should expect multiple calls toonAttach
and listeners registered throughaddAttachListener
during its lifetime.
27B1978F-9118-49D3-84C2-F4F48857F9DE