Form
Structured form layout with labels, descriptions, and validation messages.
Installation
dotnet add package Lumeo
One-time app setup (AddLumeo(), CSS & JS) is covered in the
installation guide.
Usage
@using Lumeo <Form />
66 tests across 9 files (no render-contract smoke — covered by its own tests). Auto-generated from the test suite.
When to Use
- Data collection forms such as registration, contact, or feedback forms
- Settings pages with multiple fields that need labels and validation
- Multi-field validation workflows like password changes or profile updates
- Any form requiring consistent layout with labels, descriptions, and error messages
Validation Pattern
Lumeo form inputs (Input, Select, Checkbox, Switch, Textarea, and others) do not carry
Label, Required, Error, or HelpText props directly.
Instead, wrap any input in <FormField> to attach a label, helper text, required marker, and inline error message.
The FormField cascades a FormFieldContext so that child <FormLabel> and <FormMessage>
components automatically reflect the error state without any extra wiring.
We will never share your email.
Optional.
Receive updates about your account.
Examples
This is your public display name.
We will never share your email.
Enter your email address.
Please enter a valid email address.
At least 8 characters.
Reset to initial values
The Form component takes a snapshot of the model when it's first attached. Two reset methods are available:
- Form.Reset() — clears errors, dirty fields, and submission state, but leaves the bound model values alone. Useful after a successful submit when you want to keep what the user typed but drop the validation overlay.
- Form.ResetValues() — restores every property on the model to the snapshot taken at first render, then clears errors / dirty / submission state. The "Cancel changes" button on an edit form.
Snapshot timing. The snapshot is captured on first render against the model reference you
passed. If you swap the entire model (e.g. _model = newOne),
call Form.CaptureSnapshot()
on the new model so the next ResetValues()
restores to the right baseline.
API Reference
Form<TModel>
| Prop | Type | Default | Description |
|---|---|---|---|
| Model | TModel? | — | The form's data model. A JSON snapshot is captured on init (and re-captured whenever a new instance is bound) so ResetValues can restore it later. |
| ChildContent | RenderFragment? | — | The form's fields — typically a sequence of FormFields wrapping bound inputs. |
| Validator | IFormValidator? | — | Optional synchronous validator run on submit and via ValidateField; its errors are merged into the cascaded FormContext alongside any async field-level errors. |
| Class | string? | — | Additional CSS classes merged onto the <form> element. |
| ModelTypeInfo | JsonTypeInfo<TModel>? | — | Optional source-generated JsonTypeInfo{T} for TModel, used for the init/ResetValues snapshot round-trip instead of reflection-based serialization. Without this, the snapshot uses JsonSerializer.Serialize/Deserialize<TModel> via reflection: TModel itself carries [DynamicallyAccessedMembers(All)] so ITS members survive trimming, but that annotation does NOT cascade into the types of TModel's own reference-type properties (e.g. a nested Address POCO) — their members can still be trimmed away, silently dropping nested values on ResetValues. Pass your own JsonSerializerContext-generated MyModelContext.Default.TModel here to cover the whole object graph and be fully trim-safe (#364 review). |
| AdditionalAttributes | Dictionary<string, object>? | — | Unmatched attributes splatted onto the <form> element. |
Events
| OnValidSubmit | EventCallback<TModel> | Invoked with Model on submit when validation passes (no Validator, or it reports no errors). |
| OnInvalidSubmit | EventCallback<TModel> | Invoked with Model on submit when Validator reports validation errors. |
FormField
| Prop | Type | Default | Description |
|---|---|---|---|
| Label | string? | — | Label text rendered above (or, in Horizontal mode, beside) the control, linked via <label for> to ChildContent's bound input. |
| HelpText | string? | — | Helper text shown below the control when there is no active error. |
| Error | string? | — | Manually-set error message, used when there's no parent Form context (or no Name) to source live errors from. A live error from the form's validation always takes precedence. |
| Required | bool | false | Marks the field as required, rendering a visual asterisk next to Label. |
| Orientation | Lumeo.Orientation | Lumeo.Orientation.Vertical | Layout direction: Vertical (default) stacks label above the control; Horizontal places a right-aligned label beside it in a two-column grid. |
| AutoRenderMessage | bool | true | When true (default — the simple-mode API used by the vast majority of consumers), FormField renders the validation error itself below the control. Set false when you compose the field with a child FormMessage that should own the error rendering: this suppresses FormField's own error so the two never render it twice. The error still flows into the cascaded context either way, so a deferred FormMessage can pick it up. |
| LabelWidth | string? | — | Fixed CSS width for the label column in Horizontal mode (e.g. "8rem"). Ignored in Vertical mode. |
| Name | string? | — | Field key used to look up live validation errors from the parent Form's context, and as the async-validation registration key. |
| ChildContent | RenderFragment? | — | The bound input control(s) this field wraps. |
| Class | string? | — | Additional CSS classes merged onto the field's root element. |
| AdditionalAttributes | Dictionary<string, object>? | — | Unmatched attributes splatted onto the field's root element. |
| AsyncValidator | Func<object?, Task<string?>>? | — | Optional async validator. Receives the current Value, returns null when valid or an error message string otherwise. The result is stored in Errors against Name. |
| AsyncValidationDebounceMs | int | 0 | Debounce window in ms. 0 disables debouncing. |
| AsyncValidateOn | AsyncValidationTrigger | AsyncValidationTrigger.OnBlur | When async validation runs. Defaults to OnBlur. |
| Value | object? | — | Current value of the bound input. Required for OnChange auto-triggering; also passed to the validator on blur. If unset, consumers may invoke ValidateAsync(object?) directly. |
Events
| OnValidatingChanged | EventCallback<bool> | Fired whenever IsValidating flips. |
FormItem
| Prop | Type | Default | Description |
|---|---|---|---|
| ChildContent | RenderFragment? | — | The item's content — typically a label, control, and description/message grouped as one field unit. |
| Class | string? | — | Additional CSS classes merged onto the root element. |
| AdditionalAttributes | Dictionary<string, object>? | — | Unmatched attributes splatted onto the root element. |
FormLabel
| Prop | Type | Default | Description |
|---|---|---|---|
| ChildContent | RenderFragment? | — | The label's text content. |
| Class | string? | — | Additional CSS classes merged onto the <label>. |
| AdditionalAttributes | Dictionary<string, object>? | — | Unmatched attributes splatted onto the <label>. |
FormDescription
| Prop | Type | Default | Description |
|---|---|---|---|
| ChildContent | RenderFragment? | — | Helper text describing the field, rendered below its label. |
| Class | string? | — | Additional CSS classes merged onto the <p>. |
| AdditionalAttributes | Dictionary<string, object>? | — | Unmatched attributes splatted onto the <p>. |
FormMessage
| Prop | Type | Default | Description |
|---|---|---|---|
| Class | string? | — | Additional CSS classes merged onto the rendered error <p>. |
| AdditionalAttributes | Dictionary<string, object>? | — | Unmatched attributes splatted onto the rendered error <p>. |