Skip to main content

Dialogs (Hosanna APIs)

Overview

Hosanna apps present dialogs using Hosanna views and the view-level present/dismiss APIs, not native Roku dialog nodes. Build dialog UI with standard views and present it with { isDialog: true }.

Note, standard dialogs (like all of scengraph) can be created aas per the normal roku method; but it is recommended to use Hosanna UI views for consistency, and the built-in dialog management functionality. In some cases (such as keyboard dialogs), the framework includes helper methods (see keyboardDialogUtil.showKeyboardDialog). Those utilities are documented in the keyboardDialogUtil documentation.

This guide details best practices for creating and presenting dialogs with Hosanna's view system.

Presenting dialogs vs screens

Use BaseView.present() with options.isDialog to present a dialog overlay; otherwise, it pushes a screen to the nearest NavController.

  /**
* Presents a new screen in the navigation stack or as a dialog.
*/
present(screen: ViewStruct<ViewState>, options?: IScreenPresentationOptions) {
if (options?.isDialog) {
this.showDialog(screen);
} else {
this.getNavController()?.push(screen, options?.animated);
}
}

dismiss(options?: IScreenDismissOptions) {
this.getNavController()?.pop(options?.animated);
}

Usage:

// Present as a modal dialog overlay
this.present(MyDialog({ id: 'confirmDialog' }), { isDialog: true, animated: true });

// Dismiss (if the dialog is managed by the current controller)
this.dismiss({ animated: true });

Dialog content

Create dialog content using standard Hosanna views (e.g., Group, Label, Button) and pass a ViewStruct to present.

const MyDialog = () => VGroup([
Label({ text: 'Are you sure?' }),
HGroup([
Button({ id: 'ok', text: 'OK' }).onClick(() => this.dismiss({ animated: true })),
Button({ id: 'cancel', text: 'Cancel' }).onClick(() => this.dismiss())
])
]);

// Show it
this.present(MyDialog({ id: 'dlg1' }), { isDialog: true });

Managing dialog flows

  • Use present(..., { isDialog: true }) for any modal overlay.
  • Keep focus contained; set isInitialFocus on the first actionable control.
  • Dismiss from button handlers via this.dismiss() or pass events back to the presenting view.

onDismissed callback and dialog result interface

Dialogs can expose an onDismissed callback to notify the presenting view of the result (e.g., OK/Cancel, boolean, or a more complex payload). Use this to restore focus or act on user choice.

Example usage:

const dialog = SimpleDialogView({
id: this.id + '_simpleDialog',
title: 'Simple Dialog',
message: 'This is a simple dialog.',
okText: 'OK',
cancelText: 'Cancel',
onDismissed: (value) => {
console.info('Dialog dismissed with value:', value);
this.setFocusedSubview('simpleButton');
},
});
this.present(dialog, { isDialog: true, animated: true });

Guidelines:

  • Define the dialog's onDismissed?: (value: T) => void in its state/interface for a clear contract.
  • Return a boolean for simple OK/Cancel flows; use a typed payload for complex dialogs (e.g., form data).
  • Use setFocusedSubview(...) in the presenter to restore focus to the appropriate control after dismissal.
  • Prefer passing data through the callback rather than reading internal dialog state from outside.

Best Practices

  • Provide clear titles/messages.
  • Prefer Hosanna views for dialog UI; avoid native Roku dialog nodes.
  • Keep dialog state localized and predictable; persist only what’s needed on dismissal.