glimr/forms/validator
Validation Helpers
Form validation utilities with built-in rules for common validation patterns including required fields, email format, length constraints, numeric ranges, and URL validation.
Types
File Rule Type
Defines validation rules that can be applied to file upload
fields. Rules include required file checks, file size
constraints (in KB), and allowed file extension validation.
The type parameter ctx allows custom rules to access
application context for database lookups, configuration, etc.
pub type FileRule(ctx) {
FileRequired
FileMinSize(Int)
FileMaxSize(Int)
FileExtension(List(String))
FileCustom(fn(wisp.UploadedFile, ctx) -> Result(Nil, String))
}
Constructors
-
FileRequired -
FileMinSize(Int) -
FileMaxSize(Int) -
FileExtension(List(String)) -
FileCustom(fn(wisp.UploadedFile, ctx) -> Result(Nil, String))
PendingValidation Type
Represents a validation that has been defined but not yet executed. Captures the field name, value/file, and rules to be applied. Validation is deferred until start() is called with context, allowing rules functions to be defined without needing access to context.
pub opaque type PendingValidation(ctx)
Rule Type
Defines validation rules that can be applied to form fields.
Rules include required field checks, format validation,
length constraints, and numeric range validation. The type
parameter ctx allows custom rules to access application
context for database lookups, configuration, etc.
pub type Rule(ctx) {
Required
Email
MinLength(Int)
MaxLength(Int)
Min(Int)
Max(Int)
Numeric
Url
Digits(Int)
MinDigits(Int)
MaxDigits(Int)
Custom(fn(String, ctx) -> Result(Nil, String))
}
Constructors
-
Required -
Email -
MinLength(Int) -
MaxLength(Int) -
Min(Int) -
Max(Int) -
Numeric -
Url -
Digits(Int) -
MinDigits(Int) -
MaxDigits(Int) -
Custom(fn(String, ctx) -> Result(Nil, String))
ValidationError Type
Represents a validation error for a specific field, that contains the field name and a list of error messages. Multiple rules can fail for a single field, generating multiple messages.
pub type ValidationError {
ValidationError(name: String, messages: List(String))
}
Constructors
-
ValidationError(name: String, messages: List(String))
Values
pub fn for(
form: wisp.FormData,
field_name: String,
rules: List(Rule(ctx)),
) -> PendingValidation(ctx)
Validate Field
Creates a pending validation for a form field against a list of rules. The validation is not executed until start() is called with context. Returns a PendingValidation that captures the field name, value, and rules.
Example:
validator.for(form, "email", [Required, Email])
pub fn for_file(
form: wisp.FormData,
field_name: String,
rules: List(FileRule(ctx)),
) -> PendingValidation(ctx)
Validate File Field
Creates a pending validation for a file upload field against a list of rules. The validation is not executed until start() is called with context. Returns a PendingValidation that captures the field name, file, and rules.
Example:
validator.for_file(form, "avatar", [FileRequired, FileMaxSize(2048)])
pub fn response(
errors: List(ValidationError),
) -> Result(Nil, List(ValidationError))
Convert Errors to Result
Converts a list of validation errors into a Result type. Returns Ok(Nil) if the error list is empty, or Error with the errors if any exist. Used internally by start function.
pub fn run(
req: request.Request(wisp.Connection),
ctx: ctx,
rules: fn(wisp.FormData) -> List(PendingValidation(ctx)),
data: fn(wisp.FormData) -> typed_form,
on_valid: fn(typed_form) -> response.Response(wisp.Body),
) -> response.Response(wisp.Body)
Handle Form Validation
Validates form data, transforms it using an extractor function, and executes a callback on success. Automatically extracts form data from the request, runs validation rules, transforms the validated data to a typed structure, and returns a 422 error response on failure with formatted error messages.
Example:
In your request module (e.g., app/http/requests/contact_store.gleam):
pub type Data {
Data(name: String, email: String, avatar: UploadedFile)
}
pub fn rules(form) {
[
validator.for(form, "name", [Required, MinLength(2)]),
validator.for(form, "email", [Required, Email]),
validator.for_file(form, "avatar", [RequiredFile, FileMaxSize(5000)]),
]
}
pub fn data(form) -> Data {
Data(
name: form.get(form, "name"),
email: form.get(form, "email"),
avatar: form.get_file(form, "avatar"),
)
}
In your controller:
pub fn store(req: Request, ctx: Context) -> Response {
use validated <- validator.run(req, ctx, contact_store.rules, contact_store.data)
// validated is now your Data with typed fields!
// validated.name: String
// validated.email: String
// validated.avatar: UploadedFile
redirect.to("/success")
}
pub fn start(
pending: List(PendingValidation(ctx)),
ctx: ctx,
) -> Result(Nil, List(ValidationError))
Start Validation
Executes all pending validations with the provided context and returns a combined result. Returns Ok(Nil) if all rules pass, or Error with all validation errors if any fail.