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.