Headless Mode
Use FormForge's hooks and engine without any built-in UI. Full control over rendering — bring your own components.
useFormForge
import { useFormForge } from '@formforges/react'
import { FormProvider, FormRenderer } from '@formforges/react'
function MyForm() {
const { form, values, errors, isSubmitting, submit, reset } = useFormForge({
schema,
defaultValues: { email: '' },
onSubmit: async (values) => {
await fetch('/api/submit', { method: 'POST', body: JSON.stringify(values) })
},
})
return (
<FormProvider form={form}>
<FormRenderer schema={schema} />
<div className="flex gap-3 mt-4">
<button onClick={submit} disabled={isSubmitting}>
{isSubmitting ? 'Saving...' : 'Save'}
</button>
<button onClick={reset} type="button">
Reset
</button>
</div>
<pre>{JSON.stringify(values, null, 2)}</pre>
</FormProvider>
)
}useField — custom field component
import { useField } from '@formforges/react'
function StarRating({ fieldKey }: { fieldKey: string }) {
const { value, error, touched, onChange, onBlur } = useField(fieldKey)
return (
<div>
{[1, 2, 3, 4, 5].map((star) => (
<button
key={star}
type="button"
onClick={() => onChange(star)}
onBlur={onBlur}
style={{ color: Number(value) >= star ? 'gold' : 'gray' }}
>
★
</button>
))}
{touched && error && <p>{error}</p>}
</div>
)
}createForm — no React
import { createForm } from '@formforges/core'
const form = createForm({
schema,
onSubmit: async (values) => console.log(values),
})
// Subscribe to a single field
const unsub = form.store.subscribeField('email', () => {
console.log('email changed:', form.store.getFieldState('email')?.value)
})
form.setValue('email', 'test@example.com')
await form.validate()
await form.submit()
form.reset()
unsub()useFormForge return values
| Property | Type | Description |
|---|---|---|
form | FormInstance | Raw form instance |
values | TValues | Current field values (reactive) |
errors | Record<string, string | null> | Current errors |
isSubmitting | boolean | Submit in progress |
isSubmitted | boolean | Submitted successfully |
submit | () => Promise<void> | Trigger validation + submit |
reset | () => void | Reset to default values |