Skip to main content

Action Dialog

DyonaActionDialog collects an action's parameters with a DyonaForm before Action Engine executes it. It is the parameter-entry layer on top of Action Engine.

Flow​

DyonaAction
requiresParameters: true
↓
DyonaActionDialog
↓
DyonaForm
↓
valid submit
↓
context.parameters
↓
executeDyonaAction()
↓
consumer executor

Reject order with reason​

This record action needs a rejection reason before it can run.

const rejectAction: DyonaAction = {
id: 'reject-order',
label: 'Reject order',
scope: 'record',
requiresParameters: true,
};

const context: DyonaActionContext = {
sourceId: 'orders',
record: {
id: 1024,
customer: 'Acme Corp',
status: 'pending',
},
};

The dialog form asks for a required rejectionReason select and optional comments textarea. After a valid submit, its normalized values are assigned to context.parameters in the execution context received by the executor.

DyonaActionDialogConfig​

  • schema: the DyonaFormSchema rendered inside the dialog.
  • initialValues: optional DyonaForm values used to prefill the form.
  • maxWidth: optional dialog width: xs, sm, md, lg, xl, or false.
  • fullWidth: optionally makes the dialog use the available width up to maxWidth.

Main props​

  • open controls whether the dialog is visible.
  • action is the DyonaAction to execute.
  • context is the action context; form values are added as context.parameters in the execution context.
  • config supplies the dialog form and layout configuration.
  • executor executes the action through Action Engine.
  • dataSourceExecutor resolves form data when a field needs remote autocomplete data.
  • onClose closes the dialog in the consuming component.
  • onResult receives an action result.
  • onExecutionError receives an exception thrown while executing the action.

executor and dataSourceExecutor have separate responsibilities: the former executes the business action, while the latter resolves data required by the form, such as remote autocomplete options.

Behavior​

  • The component renders only when action.requiresParameters is true.
  • An invalid submit does not execute the action.
  • A valid submit assigns normalized form values to context.parameters in the execution context.
  • It prevents a second execution while one is in progress.
  • While executing, Cancel, Escape, and backdrop close are blocked.
  • A result with success: true is reported through onResult and closes the dialog.
  • A result with success: false is reported through onResult and keeps the dialog open.
  • An executor exception calls onExecutionError and keeps the dialog open.

Complete example​

import {useState} from 'react';
import {
DyonaActionDialog,
type DyonaAction,
type DyonaActionContext,
type DyonaActionExecutor,
type DyonaActionResult,
} from '@typhonsoftware/dyona-form';

const rejectAction: DyonaAction = {
id: 'reject-order',
label: 'Reject order',
scope: 'record',
requiresParameters: true,
};

const context: DyonaActionContext = {
sourceId: 'orders',
record: {
id: 1024,
customer: 'Acme Corp',
status: 'pending',
},
};

const dialogConfig = {
schema: {
title: 'Reject order',
hideSingleTab: true,
tabs: [
{
id: 'rejection',
title: 'Rejection details',
rows: [
{
columns: [
{
name: 'rejectionReason',
label: 'Rejection reason',
type: 'select' as const,
required: true,
options: [
{value: 'out-of-stock', label: 'Out of stock'},
{value: 'pricing-error', label: 'Pricing error'},
{value: 'customer-request', label: 'Customer request'},
],
fullWidth: true,
},
],
},
{
columns: [
{
name: 'comments',
label: 'Comments',
type: 'textarea' as const,
fullWidth: true,
},
],
},
],
},
],
},
initialValues: {comments: ''},
maxWidth: 'sm' as const,
fullWidth: true,
};

const rejectOrder: DyonaActionExecutor = async ({context}) => {
const result: DyonaActionResult = {
success: true,
message: `Order ${context.record?.id} rejected`,
data: {
rejectionReason: context.parameters?.rejectionReason,
comments: context.parameters?.comments,
},
refresh: [{sourceId: 'orders'}],
};

return result;
};

export function RejectOrderAction() {
const [open, setOpen] = useState(false);

return (
<>
<button onClick={() => setOpen(true)}>Reject order</button>

<DyonaActionDialog
open={open}
action={rejectAction}
context={context}
config={dialogConfig}
executor={rejectOrder}
onClose={() => setOpen(false)}
onResult={(result) => console.log(result.message)}
onExecutionError={(error) => console.error(error)}
/>
</>
);
}

Try Action Dialog in the Lab