Documentation

Documentation versions (currently viewingVaadin 23)
New Acceleration Kits: Observability Kit, SSO Kit, and Swing Kit. Read the blog post.

Server-Side Modality

How to prevent interactions on the server side.

A dialog with a client-side modality curtain alone doesn’t disable the UI to which it belongs on the server side. If the dialog or its modality curtain is removed from the DOM on the client side, its parent UI remains active on the server and can be interacted with.

To fully prevent interactions with components that are underneath a modal dialog (or any modal component, for that matter), Flow has a feature called server-side modality. This feature makes Flow ignore interactions with all components that aren’t children of the modal component while it’s attached or marked as modal. Components that aren’t children of the modal component are said to be inert, that is, they aren’t available for interaction.

As server-side modality is purely a server-side security feature that only prevents interaction, it doesn’t add a modality curtain or change the visible state of the components in the UI. Adding a modality curtain should be handled by the component.

Router Links, and navigation in general, are an exception. Navigation is also allowed when inert, as there is no way to block navigation entirely on the server side. Also, JavaScript return values are accepted for server-initiated executions.

The UI class provides methods that allow access to the server-side modality feature. The following Vaadin components make use of the feature: Dialog, Notification, and Login View.

Modal dialogs can be stacked on top of each other, but only the most recent is active. A modal dialog can open another modal dialog, or several modeless dialogs, which again can open modal or modeless dialogs.

Note
Opening a new Dialog, Confirm Dialog, or Notification when a modal Dialog is already open automatically makes the new Dialog or Notification a child of the previously opened Dialog. Closing the "parent" Dialog also closes all subsequently opened Dialogs and Notifications.

The implementation relies on a server-side-only state tree feature called InertData, which makes it possible to stop a component/element/state node and its children from accepting any updates from the client side. By default, the inert state is inherited to child nodes. However, any child can declare itself as ignoring the parent’s inert state, which means that updates are allowed for itself and its children, unless these are explicitly made inert.

This documentation is focused on the usage of the following methods of a UI instance:

  • addModal(Component)

  • setChildComponentModal(Component, boolean)

  • hasModalComponent()

  • addToModalComponent(Component)

Using Modal Components

Use the UI.addModal(Component) method to add a modal component to the UI or to make an attached component modal with UI.setChildComponentModal(Component, true).

This makes inert all components that aren’t children of the modal component in the UI.

Note
If you have a modal component and you add a new one with addModal(Component), the new component is going to be the active component. Removing the modality/component returns the last modal component to active status, keeping its modality.

When the component is later removed from the UI or defined as non-modal with setChildComponentModal(Component, false), the UI is no longer inert, unless there was another modal component underneath the removed component.

// Add a modal component, and make the rest of the UI inert
UI.getCurrent().addModal(component);

/* other code*/

// Remove the modal component. The UI is no longer inert.
UI.getCurrent().remove(component);

To make an already-added component modal, use UI.setChildComponentModal(Component, boolean).

// Make a component modal, and make the rest of the UI inert
UI.getCurrent().setChildComponentModal(component, true);

/* other code*/

// Make the component non modal. The UI is no longer inert.
UI.getCurrent().setChildComponentModal(component, false);

Adding to a Modal Component

To add a component to the currently active modal component, use UI.addToModalComponent(Component), which adds the component under the current modal component.

This is intended to be used with components that aren’t added as part of a layout, such as a dialog, so that they are interactive when a modal component opens up an overlay component.

To check if there is a defined modal component, use UI.hasModalComponent(). This is usually needed if a new component is added. To be usable, it needs to be added under the modal component.

Note
When there is no active modal component, calling addToModalComponent(Component) adds the component to the UI.

Demo

An example project that demonstrates these APIs in action can be found here. This demo application contains the following views to present some possibilities with server modality:

  • Dialog Modality Showcase: Basic usage and comparison between modeless vs. client modal vs. server modal for dialogs.

  • Grid With Large Dataset: Shows a server-modal dialog on the view while a long-running process is in progress.

  • Modality on Top of Dialog: Shows how to use UI#addToModalComponent() to add a modal component to the current modal component.

2035D86E-96DE-4990-BDDC-881FD24F95DD