Preserving Contents of Embedded Applications on Refresh

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.

Using @PreserveOnRefresh When Embedding

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) {
    }
}

Identity of an Embedded Applications Being Preserved

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.

Controlling the Identity

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>