Crustack
@crustack/form

API Reference

👉 defineForm

Expects no arguments other than the form types. Returns the elements of the form, ensuring 100% type safety.

// define a form with a "title" and a "description" field
type  = { : string; : string }

// The type of the submission data, returned by `onSubmit`
type  = { : string }

// The type of the submission error, raised in `onSubmit`
type  = { : string }

export const  = <, , >()

👉 form.Root

Contains all the parts of the form.

Props

PropTypeDefault
onTryToSubmitError?
((ctx: FormCtx<TValues, TSubError, TSubData, TMeta>) => void)
-
onSubmitSettled?
(() => MaybePromise<void>)
-
onSubmitError?
((error: TSubError) => MaybePromise<void>)
-
onSubmitSuccess?
((data: TSubData) => MaybePromise<void>)
-
onChange?
((values: NoInfer<TValues>, prev: NoInfer<TValues>, ctx: FormCtx<TValues, TSubError, TSubData, TMeta>) => void)
-
onSubmit
(values: NoInfer<TValues>, ctx: FormCtx<TValues, TSubError, TSubData, TMeta>) => MaybePromise<TSubData>
-
children
ReactNode | ((ctx: FormCtx<TValues, TSubError, TSubData, TMeta>) => ReactNode)
-
initialValues
TValues
-

👉 form.Form

The same as a regular <form> with additional internals.

A single <form.Root> can contain several <form.Form>.

Prefer the onSubmit of <form.Root>

👉 form.Field

Contains the Description, Label, ErrorMessage and the Control.

Does not render any html tag.

Props

PropTypeDefault
children?
ReactNode
-
validate?
FieldValidator<TValues, TName>
-
disabled?
boolean
-
name
TName
-

👉 form.FieldArray

Similar to Field but renders an HTML element in order to semantically group the fields.

The FieldArray can be associated a Description and an ErrorMessage.

A FieldArray is touched when at least one of it's descendant Field is touched.

Props

PropTypeDefault
asChild?
boolean
-
children?
ReactNode
-
validate?
FieldArrayValidator<TValues, TName>
-
disabled?
boolean
-
name
TName
-

Data Attributes

The data attributes received by the FieldArray.

PropTypeDefault
data-touched?
"true" | undefined
-
data-invalid?
"true" | undefined
-
data-disabled?
"true" | undefined
-

👉 form.Control

Passes accessibility-related props to its immediate child.

❌ Incorrect usage: Manually overriding the id and name provided by Control

<Control>
  <input id="search" name="search" />
</Control>

✅ Correct usage: Let Control pass the id and name to the input.

<Control>
  <input />
</Control>

Attributes

The attributes received by the Control's direct child

PropTypeDefault
aria-describedby?
string | undefined
-
aria-labelledby?
string | undefined
-
aria-invalid?
"true" | undefined
-
aria-disabled?
"true" | undefined
-
data-touched?
"true" | undefined
-
data-invalid?
"true" | undefined
-
data-disabled?
"true" | undefined
-
disabled?
boolean | undefined
-
id?
string
-
name?
string
-

👉 form.Label

Label(s) associated to the Control, to be used within a Field or FieldArray.

Props

PropTypeDefault
asChild?
boolean
-

Data Attributes

The data attributes received by the Label

PropTypeDefault
data-touched?
"true" | undefined
-
data-invalid?
"true" | undefined
-
data-disabled?
"true" | undefined
-

👉 form.Description

The Description is associated to its closest valid parent. Valid parents are:

  • the Field element. The association is done with the Control
  • the FieldArray element
  • the Form element

Props

PropTypeDefault
asChild?
boolean
-

Data Attributes

The data attributes received by the Label

PropTypeDefault
data-touched?
"true" | undefined
-
data-invalid?
"true" | undefined
-
data-disabled?
"true" | undefined
-

👉 form.ErrorMessage

Displays the validation error message of the closest Field or FieldArray.

To ensure the error message is correctly read by screen readers, the ErrorMessage element is rendered also when there is no error. For more details, refer to the MDN documentation.

Props

PropTypeDefault
children?
(error: string | undefined) => ReactNode
-
asChild?
boolean
-

Data Attributes

The data attributes received by the Label

PropTypeDefault
data-touched?
"true" | undefined
-
data-invalid?
"true" | undefined
-
data-disabled?
"true" | undefined
-

Example: Split the error message on several lines

<ErrorMessage>
  {(error) => error.split(';').map((slice) => <div key={slice}>{slice}</div>)}
</ErrorMessage>

👉 form.PreventSubmit

The form submission is considered invalid when this component is rendered.

Useful to prevent submission while loading some data.

<PreventSubmit>
  <LoadingSpinner />
</PreventSubmit>

👉 form.useFormCtx

Access the type-safe form context.

Returns

PropTypeDefault
touched
FormTouched<TValues>
-
values
TValues
-
validateForm
() => void
-
tryToSubmit
(meta?: TMeta | undefined) => void
-
submission
FormSubmission<TValues, TSubError, TSubData, TMeta>
-
resetTouched
ResetTouched<TValues>
-
setTouched
SetTouched<TValues>
-
resetValues
ResetValues<TValues>
-
setValues
SetValues<TValues>
-
setFieldArrayValue
SetFieldArrayValue<TValues>
-
setFieldArrayTouched
SetFieldArrayTouched<TValues>
-
setFieldValue
SetFieldValue<TValues>
-
setFieldTouched
SetFieldTouched<TValues>
-
scrollToFirstTouchedError
ScrollToFirstTouchedError
-
resetSubmission
ResetSubmission
-
hasErrors
boolean
-
getFieldArrayValue
GetFieldArrayValue<TValues>
-
getFieldArrayTouched
GetFieldArrayTouched<TValues>
-
getFieldArrayError
GetFieldArrayError<TValues>
-
getFieldValue
GetFieldValue<TValues>
-
getFieldTouched
GetFieldTouched<TValues>
-
getFieldError
GetFieldError<TValues>
-
errorCount
{ all: number; touched: number; }
-

👉 form.useFieldCtx

Access the type-safe field context.

Returns

PropTypeDefault
value
FieldValue<TValues, TName>
-
touched
FieldTouched
-
setValue
(updater: SetFieldValueUpdater<TValues, TName>) => void
-
setTouched
(updater: SetFieldTouchedUpdater<TValues>) => void
-
name
TName
-
invalid
boolean
-
id
string
-
error
FieldError
-
disabled
boolean
-

👉 form.useFieldArrayCtx

Access the type-safe fieldArray context.

Returns

PropTypeDefault
value
FieldArrayValue<TValues, TName>
-
touched
FieldArrayTouched
-
setValue
(updater: SetFieldArrayValueUpdater<TValues, TName>) => void
-
setTouched
(updater: SetFieldArrayTouchedUpdater<TValues>) => void
-
name
TName
-
invalid
boolean
-
error
FieldArrayError
-
disabled
boolean
-

On this page