Skip to content

CommandDialog

The CommandDialog component provides a dialog interface for executing commands with built-in form handling and validation.

CommandDialog simplifies the process of presenting a command form to users within a modal dialog. It handles command execution, validation, and result management automatically.

  • Automatic form generation from command types
  • Built-in validation support
  • Field-level change tracking
  • Pre-execution transformation of values
  • Success and cancellation handling
  • Busy state management during command execution (buttons disabled, spinner shown)
  • Integration with Cratis Arc command system

For new implementations, use the same dialog pattern as other typed dialogs:

  • Open dialogs through useDialog<TResult>()
  • Close from inside the dialog through useDialogContext<TResult>()
  • await the dialog at the call site and handle [dialogResult, value]

When the value represents command execution output, use CommandResult<TResponse> as the dialog result type.

import { DialogResult, useDialog, useDialogContext } from '@cratis/arc.react/dialogs';
import { CommandResult } from '@cratis/arc/commands';
import { CommandDialog } from '@cratis/components/CommandDialog';
import { CreateProject } from './commands';
type CreateProjectResponse = {
projectId: string;
};
const CreateProjectDialog = () => {
const { closeDialog } = useDialogContext<CommandResult<CreateProjectResponse>>();
return (
<CommandDialog<CreateProject, CreateProjectResponse>
command={CreateProject}
title='Create project'
okLabel='Create'
onSuccess={(response) => {
console.log('Project created:', response.projectId);
closeDialog(DialogResult.Ok);
}}
onValidationFailure={(errors) => {
console.error('Validation failed:', errors);
}}
onCancel={() => closeDialog(DialogResult.Cancelled)}
/>
);
};
function MyComponent() {
const [CreateProjectDialogWrapper, showCreateProjectDialog] = useDialog<CommandResult<CreateProjectResponse>>(CreateProjectDialog);
const handleCreateProject = async () => {
const [dialogResult, commandResult] = await showCreateProjectDialog();
if (dialogResult === DialogResult.Ok && commandResult?.isSuccess) {
// Handle successful command response
}
};
return (
<>
<button onClick={handleCreateProject}>Create project</button>
<CreateProjectDialogWrapper />
</>
);
}

CommandDialog invokes onSuccess when command execution succeeds, and other callbacks based on the command result.

  • command: Constructor for the command type
  • title: Dialog title text
  • visible: Boolean controlling dialog visibility (defaults to true)
  • initialValues: Initial values for the command form
  • currentValues: Current values to populate the form
  • onSuccess: Callback invoked on successful command execution with the typed response
  • onFailed: Callback invoked when command execution fails with the full CommandResult<TResponse>
  • onException: Callback invoked when the command throws an exception with error messages and stack trace
  • onUnauthorized: Callback invoked when authorization fails
  • onValidationFailure: Callback invoked on validation errors with the validation results
  • onConfirm: Confirm callback from Dialog (called only after successful command execution)
  • onCancel: Cancel callback from Dialog
  • onClose: Fallback close callback from Dialog
  • okLabel: Custom text for confirm button (default: “Ok”)
  • cancelLabel: Custom text for cancel button (default: “Cancel”)
  • yesLabel, noLabel: Labels for YesNo and YesNoCancel button modes
  • buttons: DialogButtons value or custom footer content
  • resizable: Whether dialog can be resized
  • isValid: Additional validity gate combined with command form validity
  • onFieldValidate: Custom validation function for fields
  • onFieldChange: Callback when field values change
  • onBeforeExecute: Transform command values before execution
  • style: Custom CSS styles
  • contentStyle: Custom CSS styles for the dialog content area
  • width: Dialog width

CommandDialog supports the following result callbacks that are invoked based on the command execution outcome:

  • onSuccess(response: TResponse): Invoked when the command executes successfully. Receives the typed response.
  • onFailed(commandResult: CommandResult<TResponse>): Invoked when command execution fails for any reason.
  • onException(messages: string[], stackTrace: string): Invoked when the command throws an exception.
  • onUnauthorized(): Invoked when authorization fails.
  • onValidationFailure(validationResults: ValidationResult[]): Invoked on validation errors.

Multiple callbacks may fire for the same execution. For example, both onFailed and onValidationFailure will be invoked for validation errors.

  • onConfirm is executed only after command execution succeeds.
  • If onConfirm returns true, the dialog closes; otherwise it stays open.
  • If onConfirm is not provided, onClose(DialogResult.Ok) is used.
  • onCancel follows the same behavior as Dialog (true closes).
  • onClose closes unless it returns false.

CommandDialog automatically manages a busy state during command execution:

  • When the Ok/Yes button is clicked and command execution begins, all buttons are disabled and the primary button shows a loading spinner.
  • Once execution completes (success or failure), the buttons return to their normal state.
  • This prevents duplicate submissions and gives users clear visual feedback.

CommandDialog is built on top of CommandForm and Dialog, and uses command form context internally for values, validation, and execution state.

When used as an awaitable dialog, pair it with useDialogContext<CommandResult<TResponse>>() in a wrapping dialog component.

CommandDialog integrates with:

  • @cratis/arc/commands for command execution
  • @cratis/arc.react/commands for form handling
  • PrimeReact Dialog component for UI