@jsvision/forms / formDialog
Function: formDialog()
Documented in: Form Dialog
formDialog<
S,I>(host,options):Promise<output<S> |null>
Defined in: form-dialog.ts:192
Run a form in a modal dialog and resolve to the coerced values on OK, or null on Cancel / Esc / close-box / a quit-close.
The dialog creates the form (via createForm), hands it to body(form) to bind widgets, then runs modally. OK marks every field touched, validates (force-running any async validators), runs the optional onSubmit inside the gate, and — only if all of that passes — closes and resolves the coerced z.output<S>. An invalid OK keeps the dialog open with errors revealed. The dialog is sealed while a submit is in flight (Cancel / Esc / quit are inert). The form is always disposed on close, on every path (including a body or onSubmit that throws).
Type Parameters
S
S extends ZodObject<Readonly<{[k: string]: $ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; }>, $strip>
I
I extends Record<keyof output<S>, unknown>
Parameters
host
ModalDialogHost
A modal host — the createApplication result satisfies it directly.
options
FormDialogOptions<S, I>
The schema, raw initial values, the body(form) builder, and optional onSubmit / okText / async options; width and height are required.
Returns
Promise<output<S> | null>
The coerced values on OK, or null on any other close.
Example
import { formDialog } from '@jsvision/forms';
import { at, createApplication, Group, Input, Label } from '@jsvision/ui';
import { resolveCapabilities } from '@jsvision/core';
import { z } from 'zod';
const app = createApplication({ caps: resolveCapabilities().profile });
const api = { save: async (v: { name: string; port: number }): Promise<void> => void v };
const schema = z.object({ name: z.string().min(1, 'Required'), port: z.coerce.number().int().min(1) });
const values = await formDialog(app, {
schema,
initial: { name: '', port: '8080' }, // RAW editing values (port edited as a string)
title: ' Edit server ',
width: 44,
height: 9,
body: (form) => {
const g = new Group();
const input = at(new Input({ value: form.field('name').value }), 13, 1, 24, 1);
const label = at(new Label('~N~ame', input), 2, 1, 10, 1);
g.add(label);
g.add(input);
return g;
},
onSubmit: async (v) => { await api.save(v); }, // runs INSIDE the gate; reject → the dialog stays open
});
if (values) console.log('saved', values.name, values.port); // null on Cancel/Esc