Hooks

useFormFieldEmit

A helper hook for custom input components that want to participate in <Form> validation timing. Returns four emitters (onBlur, onFocus, onInput, onChange) that push their corresponding events up to the parent Form so it can run validation, track dirty/touched/blurred state, and trigger error UI.

Basic Usage

Call the hook at component setup, then wire each emitter onto the matching native event.

Try focusing in/out — validation events flow to the Form

<script lang="ts">
  import { useFormFieldEmit } from 'sv5ui';

  // Each method is a safe no-op outside a Form — wire them unconditionally.
  const emit = useFormFieldEmit();
</script>

<!-- Hook the four emitters into the input's native events. -->
<input
  type="text"
  onblur={emit.onBlur}
  onfocus={emit.onFocus}
  oninput={emit.onInput}
  onchange={emit.onChange}
/>

Pair with useFormField

The two hooks compose: useFormField() reads context (name, ariaId, error, size); useFormFieldEmit() writes events back.

Both hooks
<!-- useFormField  → read context (name, ariaId, error, size)
     useFormFieldEmit → write events back to the parent Form        -->

<script lang="ts">
  import { useFormField, useFormFieldEmit } from 'sv5ui';

  const formField = useFormField();   // READ
  const emit = useFormFieldEmit();    // WRITE
</script>

<input
  id={formField?.ariaId}
  aria-invalid={!!formField?.error || undefined}
  onblur={emit.onBlur}
  oninput={emit.onInput}
  onchange={emit.onChange}
  onfocus={emit.onFocus}
/>

Building a Custom Input

A complete custom input — pulls the FormField's ariaId and name from context, emits all four events to the parent Form.

No live demo — this snippet is a template for building your own input. When dropped inside <Form> + <FormField>, it participates in validation just like the built-in <Input>.

<script lang="ts">
  // Build your own input that integrates with Form validation.
  import { useFormField, useFormFieldEmit } from 'sv5ui';

  let { value = $bindable() }: { value?: string } = $props();

  const formField = useFormField();
  const emit = useFormFieldEmit();
</script>

<input
  bind:value
  id={formField?.ariaId}
  name={formField?.name}
  aria-invalid={!!formField?.error || undefined}
  onblur={emit.onBlur}
  onfocus={emit.onFocus}
  oninput={emit.onInput}
  onchange={emit.onChange}
  class="rounded border px-3 py-1.5"
/>

Safe Outside a Form

When there's no parent Form, every emitter is a no-op. You can reuse the same component everywhere without checking the context.

Useful when shipping reusable inputs that may be dropped into Form-driven flows OR ad-hoc layouts.

<script lang="ts">
  // Same component used INSIDE a Form/FormField AND outside it.
  // useFormFieldEmit() returns no-op functions when there's no Form
  // context — no errors, no special handling needed.
  import { useFormFieldEmit } from 'sv5ui';

  const emit = useFormFieldEmit();
</script>

<input onblur={emit.onBlur} oninput={emit.onInput} />

Return Value

An object with four void-returning methods. Each fires its event on the parent Form, or no-ops if there is none.

MethodType
onBlur() => void
onFocus() => void
onInput() => void
onChange() => void