Expand description
Form parsing, validation, and HTML rendering.
§Two names, two layers (gaps2 #19)
FormValidatetrait (the primitive, wasForm): a struct implements this to provide avalidate(&HashMap)method. The#[derive(Form)]macro emits it.Form<T>extractor (the axum entry point): wraps the parsed-and-validatedTin aResult<T, FormErrors>. Use in handler signatures:Form<ContactForm>.
The trait used to be called Form too, but that collided with
the extractor type in the same module. The name with generics
went to the extractor (matches axum::extract::Form<T> /
axum::Json<T> shape) and the trait got the more descriptive
FormValidate.
The piece that fills out the request-handling story between axum’s
Form<T> extractor (raw key/value access) and a typed Rust struct
(the application’s view of validated input). umbral’s first cut is
the primitive layer richer form abstractions sit on top of.
§v1 shape
Fieldtypes per HTML input shape (TextField,IntegerField,EmailField,PasswordField,BooleanField,DateField,TimeField).- Field-level validators (
Required,MinLength,MaxLength, [Pattern]) plus the convenience built-in checks each field type does for its own shape (e.g.EmailFieldrunsPatternagainst an email regex by default). ValidationErrorsis a map of field-name -> error messages. Forms accumulate every per-field error before returning, so the user sees the whole form’s problems at once.- HTML rendering: every field type has
Field::render_htmlthat emits a single<input>(or<textarea>) with the righttype,name,value, and arequiredattribute when the field is required.
§v1 caps
- No
#[derive(Form)]macro. Users compose forms by hand:LoginForm::validate(&form_data)is a function that reads each field, accumulates errors, returns either the typed struct orErr(ValidationErrors). The derive lands as a future round. - No file uploads (multipart); HTML-only.
- No localized error messages.
Structs§
- Email
Format - A simple “must look like an email” check. Not RFC 5322 strict —
covers the 99% case (one
@, non-empty local part, dot in the domain). Users with stricter needs swap in a real regex. - Field
- A single form field: name + kind + validators. The field doesn’t
own its parsed value;
validatereads from the form-data map and pushes errors onto the accumulator. - Form
- Axum extractor that validates a form body before the handler
runs. On extraction success the wrapped result is
Ok(T)(the validated struct); on validation failure the wrapped result isErr(FormErrors). The HTTP layer never rejects — handlers ALWAYS see aForm<T>and decide what to render viaSelf::into_result. - Form
Errors - Form-validation error envelope. Wraps the ORM’s
WriteErrorso every surface (REST 400 bodies, admin form spans, HTML form renders) sees the same structured shape. The template helperas_template_ctxproduces the flat single-string-per-field view that most form templates ask for. - MaxLength
- The field’s length (in characters) must be at most
n. - MinLength
- The field’s length (in characters) must be at least
n. - Regex
Format - Regex-pattern validator — the catch-all shape for “value must match this format”. Reject the field with a user-supplied message when the pattern doesn’t match.
- Required
- The field must not be empty.
- Validation
Errors - A collection of per-field validation errors. Forms accumulate these and return the whole map at once.
Enums§
- Input
Kind - What HTML
<input type>a field renders as. The form module uses this forrender_html; it’s the same set the admin’sinput_kindproduces. - PkKind
- How to parse a submitted FK id string. Resolved from the target model’s PK SqlType at render/validate time.
Constants§
- PHONE_
E164_ PATTERN - E.164 international phone-number format — the standard the
telecoms industry uses.
+<country code><subscriber number>where the country code is 1-3 digits and the subscriber number is up to 14 digits, no spaces or punctuation. - URL_
PATTERN - URL validator — http(s) only, requires a host, accepts an
optional path/query/fragment. Conservative on purpose:
ftp://,mailto:, etc. get rejected so a form that promises “URL” doesn’t end up persisting a non-web scheme.
Traits§
- Form
Validate - The contract a typed form satisfies.
validatereads form data (aHashMap<String, String>, the natural shape afterserde_urlencodedor axum’sFormextractor) and produces either the typed struct or aValidationErrorsmap describing every problem at once. - Validator
- One validator’s verdict.