title | order | layout |
---|---|---|
Preserve on Refresh when Embedding |
7 |
page |
Since Vaadin 14.1, it is possible to have embedded applications preserve their contents on refresh, much like one can do with normal Vaadin applications, using @PreserveOnRefresh
annotation.
However, due to the nature of embedded Vaadin applications, there are few changes to how the annotations is used when embedding components.
In the normal annotation case, the @PreserveOnRefresh
annotation is added onto the Component
the user wishes the preserve.
When preserving embeddable web components, the @PreserveOnRefresh
annotation is added onto the WebComponentExporter
class.
The preserving then affects all embedded instances produced by that exporter.
@PreserveOnRefresh
public class EmbeddedComponentExporter
extends WebComponentExporter<EmbeddedComponent> {
public EmbeddedComponentExporter() {
super("embedded-component");
}
@Override
protected void configureInstance(
WebComponent<EmbeddedComponent> webComponent,
EmbeddedComponent component) {
}
}
If you want to have two versions of the web component, one that is preserved, and one that is not, you can simply export the same Component
twice under different tags:
@PreserveOnRefresh
public class EmbeddedComponentExporter1
extends WebComponentExporter<EmbeddedComponent> {
public EmbeddedComponentExporter1() {
super("embedded-component-1");
}
@Override
protected void configureInstance(
WebComponent<EmbeddedComponent> webComponent,
EmbeddedComponent component) {
}
}
public class EmbeddedComponentExporter2
extends WebComponentExporter<EmbeddedComponent> {
public EmbeddedComponentExporter2() {
super("embedded-component-2");
}
@Override
protected void configureInstance(
WebComponent<EmbeddedComponent> webComponent,
EmbeddedComponent component) {
}
}
Since the embedded Vaadin applications live on pages that themselves are not usually Vaadin applications, the embedded web component backed by server-side Vaadin Component
uses a generated id to link those two facets together.
When the custom tag on the client-side is upgraded as Vaadin Web Component and it is connected to the Component on the server-side, it sends an identifier to the server so that Vaadin can match the two components.
Each embedded web component generates an identifier for itself, which is its tag + a running counter.
For example, two <embedded-component>
web components on a page might have identifiers EmbeddedComponent-0
and EmbeddedComponent-1
.
In order to guarantee that a web component instance is uniquely preserved and its state does not leek to other instances of that web component, the generated id is combined with window name, and the state is stored to user’s session.
This enables storing an restoring of user’s web components inside a web location.
However, since the identifier is essentially a running counter, if an instance of a web component is embedded on two locations withing the embedding application, it is possible that the states get "mixed".
Say that the user is at location example.com/location-1
, where an instance of embedded-component
is embedded.
Now, if the user were to navigate to example.com/location-2
and that page also had an instance of embedded-component
embedded, the preserved state would be displayed on the embedded-component
in the new location location-2
.
If you want the state of the embedded web component to be shared between pages, then you do not need to do anything. However, since the identification is a running number, having multiple instances of the same component on different pages might yield unexpected behavior.
In order to make sure that the state is preserved in the manner you wish, you can assign an explicit id
attribute to the web component to get consistent behavior.
Assign an id
attribute to the embedded web component to be explicit about its identity.
The manually assigned id
will be used in place of the generated component identifier, providing a consistent identity for the embedded web component.
<div>
<embedded-component id="uniquely-preserved"></embedded-component>
</div>
The id
can then be used to either make sure, that the state is preserved across locations or that it is not preserved.
If you want to have the component’s state be preserved across locations, assign the same id
on the web component in both locations:
<!-- location-1 -->
<div>
<embedded-component id="cross-preserved"></embedded-component>
</div>
<!-- location-2 -->
<div>
<embedded-component id="cross-preserved"></embedded-component>
</div>
On the other hand, if you want to make sure that the state is preserved only within a particular location, assign the web component instances different id
attributes in different locations:
<!-- location-1 -->
<div>
<embedded-component id="location-1-preserved"></embedded-component>
</div>
<!-- location-2 -->
<div>
<embedded-component id="location-2-preserved"></embedded-component>
</div>