Skip to content

feat: typed custom events between form and fields#3

Closed
LouisHaftmann wants to merge 1 commit into
masterfrom
prototype/form-events
Closed

feat: typed custom events between form and fields#3
LouisHaftmann wants to merge 1 commit into
masterfrom
prototype/form-events

Conversation

@LouisHaftmann

Copy link
Copy Markdown
Contributor

Summary

Prototype for a bidirectional, fully-typed custom event channel between a form and its fields, built on top of the existing hookable instance.

  • field → form: field.events.callHook(name, payload) emits; form.events.hook(name, (payload, field) => …) listens and receives the sender field.
  • form → field: form.events.callHook(name, payload) emits (broadcast to all field listeners); field.events.hook(name, payload => …) listens.
  • Event payloads are declared app-wide via a module-augmentable Register interface, keyed by direction:
declare module '@falcondev-oss/form-core' {
  interface Register {
    events: {
      toForm: { validated: { ok: boolean }; requestScroll: void } // field → form
      toField: { flash: { color: string } }                        // form → field
    }
  }
}

Directions are type-enforced (a form can't emit a toForm event, and vice versa), unknown events / wrong payloads are rejected, and void events take no payload. hook/hookOnce/callHook naming mirrors hookable.

Implementation

  • One extra createHooks() bus per form (separate from lifecycle hooks); names namespaced by direction (toForm: / toField:).
  • events facade added to the form handle and to each FormField.
  • useFormHandles (vue) aggregates events across forms.

Tests

  • Runtime (core.test.ts): field→form w/ sender, form→field, broadcast, void payload, direction isolation.
  • Types (types.test-d.ts): typed payloads + sender, direction enforcement, unknown/wrong/missing payloads rejected.

Type-check ✓, lint ✓, tests green (only the pre-existing field > readonly failure remains, unrelated).

Note: .patch(partial, metadata) is designed but not in this PR.

Add a bidirectional event channel on top of hookable: fields emit
field → form events (the form listens and receives the sender field),
and the form emits form → field events (fields listen). Payloads are
declared app-wide via a module-augmentable `Register` interface, keyed
by direction (`toForm` / `toField`).
@LouisHaftmann LouisHaftmann assigned DrJume and unassigned DrJume Jul 23, 2026
@LouisHaftmann
LouisHaftmann requested a review from DrJume July 23, 2026 13:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants