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: theDyonaFormSchemarendered inside the dialog.initialValues: optionalDyonaFormvalues used to prefill the form.maxWidth: optional dialog width:xs,sm,md,lg,xl, orfalse.fullWidth: optionally makes the dialog use the available width up tomaxWidth.
Main props
opencontrols whether the dialog is visible.actionis theDyonaActionto execute.contextis the action context; form values are added ascontext.parametersin the execution context.configsupplies the dialog form and layout configuration.executorexecutes the action through Action Engine.dataSourceExecutorresolves form data when a field needs remote autocomplete data.onClosecloses the dialog in the consuming component.onResultreceives an action result.onExecutionErrorreceives 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.requiresParametersistrue. - An invalid submit does not execute the action.
- A valid submit assigns normalized form values to
context.parametersin 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: trueis reported throughonResultand closes the dialog. - A result with
success: falseis reported throughonResultand keeps the dialog open. - An executor exception calls
onExecutionErrorand 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)}
/>
</>
);
}