Skip to content

Commands and messages

In addition to returning State or Data, actions can return UICommand objects to trigger browser-level behavior — closing dialogs, setting the window title, changing the favicon, or chaining actions.


Return a Message to show a toast notification in the browser:

@Override
public Object handleAction(String actionId, HttpRequest httpRequest) {
return Message.builder().text("Operation successful!").build();
}

See UI effects for full Message options (variant, position, title, duration).


Return a Dialog to open a modal:

@Override
public Object handleAction(String actionId, HttpRequest httpRequest) {
if ("open-dialog".equals(actionId)) {
return Dialog.builder()
.closeButtonOnHeader(true)
.content(Form.builder()
.title("Dialog form")
.content(List.of(
Button.builder()
.label("Close dialog")
.actionId("close-dialog")
.build()
))
.build())
.build();
}
return null;
}

The Dialog wraps any component as its content. Set closeButtonOnHeader(true) to show an X button.


Return UICommand with type CloseModal to close the currently open dialog:

if ("close-dialog".equals(actionId)) {
return UICommand.builder().type(UICommandType.CloseModal).build();
}

This is typically used by a button inside the dialog itself.

// Full open-and-close-dialog example
@Override
public Object handleAction(String actionId, HttpRequest httpRequest) {
if ("open-dialog".equals(actionId)) {
return Dialog.builder()
.closeButtonOnHeader(true)
.content(Form.builder()
.title("Confirm")
.content(List.of(
Button.builder()
.label("Close")
.actionId("close-dialog")
.build()
))
.build())
.build();
}
if ("close-dialog".equals(actionId)) {
return UICommand.builder().type(UICommandType.CloseModal).build();
}
return null;
}

Change the browser tab/window title:

if ("setWindowTitle".equals(actionId)) {
String title = httpRequest.getString("title");
return UICommand.builder()
.type(UICommandType.SetWindowTitle)
.data(title)
.build();
}

The data field carries the new title string.


Change the browser favicon:

if ("setFavicon".equals(actionId)) {
String iconUrl = httpRequest.getString("favIcon");
return UICommand.builder()
.type(UICommandType.SetFavicon)
.data(iconUrl)
.build();
}

data is the URL or path to the icon file.


Chain to another action without user interaction:

// Returning this command immediately triggers "action-2"
return UICommand.runAction("action-2");

The shorthand UICommand.runAction(actionId) is equivalent to:

UICommand.builder().type(UICommandType.RunAction).data("action-2").build()

Use for: redirect after save, auto-refresh after a background operation.

@Override
public Object handleAction(String actionId, HttpRequest httpRequest) {
if ("action-2".equals(actionId)) {
return Message.builder().text("action-2 ran").build();
}
// Any other action chains to action-2
return UICommand.runAction("action-2");
}

Navigate the browser to a route:

return UICommand.navigateTo("/dashboard");

Or using URI:

return URI.create("/dashboard");

Both navigate the user to the given path.


When a component has @ConfirmOnNavigationIfDirty (or is a CRUD create/edit view), the frontend tracks unsaved changes. Return UICommand.markAsDirty() or UICommand.markAsClean() from any action to control that state programmatically:

@ConfirmOnNavigationIfDirty
public class MyForm {
String name;
@Toolbar
Object save() {
// persist ...
return List.of(
Message.builder().text("Saved").build(),
UICommand.markAsClean() // clears the dirty flag
);
}
@Toolbar
Object generateDraft() {
// populate fields without saving
return UICommand.markAsDirty(); // warn user if they navigate away
}
}

CRUD create and edit views activate dirty-state tracking automatically — no annotation needed on the orchestrator.


UICommandTypeShorthandEffectdata field
CloseModalClose the current open dialog
SetWindowTitleSet the browser tab titleNew title string
SetFaviconChange the browser faviconFavicon URL
RunActionUICommand.runAction(id)Trigger another actionTarget actionId
NavigateToUICommand.navigateTo(path)Navigate the browser to a routeRoute string
PushStateToHistoryUICommand.pushStateToHistory(url)Update browser URL without navigationURL string
MarkAsDirtyUICommand.markAsDirty()Mark the component as having unsaved changes
MarkAsCleanUICommand.markAsClean()Clear the dirty flag after a successful save

Alternatively, return a URI object to navigate the browser to a route.