@jsvision/forms / bindField
Function: bindField()
bindField<
T>(field,view):void
Defined in: bind-field.ts:56
Wire a field's touched flag to a widget's focus: the field becomes touched the first time focus leaves the widget (a blur), never merely by mounting it or focusing into it. This is how a form shows a validation error only after the user has visited and left a field, matching submit() (which marks every field touched at once).
Behavior and constraints:
- First-leave only. Touched flips on the
focused: true → falsetransition. It never fires on mount or on focus-in, and re-focusing then leaving again is harmless (touched staystrue). - View-scoped lifetime. The focus effect is owned by the view and torn down when the view unmounts — no manual cleanup, no store-level subscription. Call it any time (before or after the view is mounted); the wiring is deferred to the view's mount.
- Idempotent per (field, view). Calling it twice for the same pair wires the effect once.
- Foreign handles throw.
fieldmust be a handle from this form'screateForm; any other object throws FormFieldError (there is no touched seam registered for it).
Use it alongside a direct value binding (new Input({ value: field.value })) or a choice adapter (bindRadio/bindCheck) — those carry the value two-way; bindField adds only the touched signal.
Type Parameters
T
T
Parameters
field
Field<T>
The field handle whose touched flag to drive.
view
View
The focusable widget bound to that field.
Returns
void
Throws
If field was not produced by this form's createForm.
Example
import { Group, Input, createEventLoop } from '@jsvision/ui';
import { resolveCapabilities } from '@jsvision/core';
import { createForm, bindField } from '@jsvision/forms';
import { z } from 'zod';
const form = createForm({ schema: z.object({ email: z.string().email() }), initial: { email: '' } });
const field = form.field('email');
const input = new Input({ value: field.value }); // two-way value binding
bindField(field, input); // touched once focus leaves the field
const root = new Group();
root.add(input);
const caps = resolveCapabilities({ env: {}, platform: 'linux' }).profile;
const loop = createEventLoop({ width: 30, height: 3 }, { caps });
loop.mount(root);
loop.focusView(input);
// field.touched() stays false while focused; it becomes true the first time focus moves away.