Skip to content

Forms

wybthon.forms

forms

Form state, validation helpers, and accessibility attribute utilities.

This module gives you a small but complete toolkit for building controlled form components on top of Wybthon's reactive primitives:

See Also

Classes:

Name Description
FieldState

Signals representing a field's value, error message, and touched state.

Functions:

Name Description
required

Validate that a value is present and non-empty.

min_length

Validate that the stringified value length is at least n.

max_length

Validate that the stringified value length is at most n.

email

Validate a basic email address format with a lightweight regex.

validate

Return the first validation error, or None when all validators pass.

form_state

Create a form state map from a dict of initial values.

bind_text

Bind a text input to a field with validation on every input event.

bind_checkbox

Bind a checkbox input to a boolean field.

bind_select

Bind a <select> element to a field, updating value on change.

on_submit

Create a submit handler that prevents default and forwards to handler.

validate_field

Validate a single field and update its error and touched signals.

validate_form

Validate every field in a form against a rules map.

on_submit_validated

Submit handler that validates the whole form before calling handler.

rules_from_schema

Build a validators map from a small declarative schema.

a11y_control_attrs

Return ARIA attributes for an input or select control bound to a field.

error_message_attrs

Return attributes for an accessible error-message container.

FieldState dataclass

FieldState(value: Signal[Any], error: Signal[Optional[str]], touched: Signal[bool])

Signals representing a field's value, error message, and touched state.

Attributes:

Name Type Description
value Signal[Any]

Signal holding the current input value.

error Signal[Optional[str]]

Signal holding the latest validation error message, or None when valid.

touched Signal[bool]

Signal that becomes True once the user has interacted with the field. Useful for delaying error display until the user has had a chance to respond.

required

required(message: str = 'This field is required') -> Validator

Validate that a value is present and non-empty.

Parameters:

Name Type Description Default
message str

Error message used when the value is missing or blank.

'This field is required'

Returns:

Type Description
Validator

A validator that returns message for None or empty strings

Validator

(after strip()), otherwise None.

min_length

min_length(n: int, message: Optional[str] = None) -> Validator

Validate that the stringified value length is at least n.

Parameters:

Name Type Description Default
n int

Minimum allowed length.

required
message Optional[str]

Optional override for the default error message.

None

Returns:

Type Description
Validator

A validator that returns the message when `len(str(value)) <

Validator

nor whenvalueisNone, otherwiseNone`.

max_length

max_length(n: int, message: Optional[str] = None) -> Validator

Validate that the stringified value length is at most n.

Parameters:

Name Type Description Default
n int

Maximum allowed length.

required
message Optional[str]

Optional override for the default error message.

None

Returns:

Type Description
Validator

A validator that returns the message when `len(str(value)) >

Validator

nor whenvalueisNone, otherwiseNone`.

email

email(message: str = 'Invalid email address') -> Validator

Validate a basic email address format with a lightweight regex.

The validator accepts None and empty strings as valid so it can be combined with required (which handles the "missing" case explicitly).

Parameters:

Name Type Description Default
message str

Error message used when the value does not match.

'Invalid email address'

Returns:

Type Description
Validator

A validator returning message on bad input, otherwise

Validator

None.

validate

validate(value: Any, validators: List[Validator]) -> Optional[str]

Return the first validation error, or None when all validators pass.

Parameters:

Name Type Description Default
value Any

Value to validate.

required
validators List[Validator]

Ordered list of validators applied with short-circuit semantics.

required

Returns:

Type Description
Optional[str]

The error message from the first failing validator, or None

Optional[str]

if every validator returns None.

form_state

form_state(initial: Dict[str, Any]) -> Dict[str, FieldState]

Create a form state map from a dict of initial values.

Parameters:

Name Type Description Default
initial Dict[str, Any]

Mapping of field name to initial value.

required

Returns:

Type Description
Dict[str, FieldState]

A dict mapping each field name to a freshly-created

Dict[str, FieldState]

bind_text

bind_text(field: FieldState, *, validators: Optional[List[Validator]] = None) -> Dict[str, Any]

Bind a text input to a field with validation on every input event.

Parameters:

Name Type Description Default
field FieldState

Target FieldState.

required
validators Optional[List[Validator]]

Optional list of validators. When provided, the field's error signal is updated on every keystroke.

None

Returns:

Type Description
Dict[str, Any]

Props dict suitable for spreading onto a text input

Dict[str, Any]

(value + on_input).

bind_checkbox

bind_checkbox(field: FieldState) -> Dict[str, Any]

Bind a checkbox input to a boolean field.

Parameters:

Name Type Description Default
field FieldState

Target FieldState (treated as holding a bool).

required

Returns:

Type Description
Dict[str, Any]

Props dict suitable for spreading onto a checkbox

Dict[str, Any]

(checked + on_change).

bind_select

bind_select(field: FieldState) -> Dict[str, Any]

Bind a <select> element to a field, updating value on change.

Parameters:

Name Type Description Default
field FieldState

Target FieldState.

required

Returns:

Type Description
Dict[str, Any]

Props dict suitable for spreading onto a <select> element

Dict[str, Any]

(value + on_change).

on_submit

on_submit(handler: Callable[[Dict[str, FieldState]], Any], form: Dict[str, FieldState]) -> Callable[[Any], Any]

Create a submit handler that prevents default and forwards to handler.

Parameters:

Name Type Description Default
handler Callable[[Dict[str, FieldState]], Any]

Callback invoked with the form state when submit fires.

required
form Dict[str, FieldState]

Form state map produced by form_state.

required

Returns:

Type Description
Callable[[Any], Any]

An event handler suitable for on_submit= on a <form>.

validate_field

validate_field(field: FieldState, validators: Optional[List[Validator]] = None) -> Optional[str]

Validate a single field and update its error and touched signals.

Parameters:

Name Type Description Default
field FieldState

Target FieldState.

required
validators Optional[List[Validator]]

Validators to apply. When omitted or empty, the field is treated as valid.

None

Returns:

Type Description
Optional[str]

The first error message produced by the validators, or None

Optional[str]

when the field is valid.

validate_form

validate_form(form: Dict[str, FieldState], rules: Dict[str, List[Validator]]) -> Tuple[bool, Dict[str, Optional[str]]]

Validate every field in a form against a rules map.

Mutates each field's touched and error signals as a side effect.

Parameters:

Name Type Description Default
form Dict[str, FieldState]

Form state map (typically produced by form_state).

required
rules Dict[str, List[Validator]]

Mapping from field name to a list of validators. Unknown field names are ignored.

required

Returns:

Type Description
bool

A (is_valid, errors) tuple where is_valid is True only

Dict[str, Optional[str]]

when every validator passes and errors maps each field name

Tuple[bool, Dict[str, Optional[str]]]

to its current error message (or None).

on_submit_validated

on_submit_validated(rules: Dict[str, List[Validator]], handler: Callable[[Dict[str, FieldState]], Any], form: Dict[str, FieldState]) -> Callable[[Any], Any]

Submit handler that validates the whole form before calling handler.

Prevents the default submit action, validates via validate_form, and invokes handler only when validation passes.

Parameters:

Name Type Description Default
rules Dict[str, List[Validator]]

Mapping from field name to a list of validators.

required
handler Callable[[Dict[str, FieldState]], Any]

Callback invoked with the form state on success.

required
form Dict[str, FieldState]

Form state map produced by form_state.

required

Returns:

Type Description
Callable[[Any], Any]

An event handler suitable for on_submit= on a <form>.

rules_from_schema

rules_from_schema(schema: Dict[str, Dict[str, Any]]) -> Dict[str, List[Validator]]

Build a validators map from a small declarative schema.

Supported per-field keys:

  • required: bool or str (if a string, it is used as the custom message).
  • min_length: int. Optional custom message via min_length_message.
  • max_length: int. Optional custom message via max_length_message.
  • email: bool or str (if a string, it is used as the custom message).

Parameters:

Name Type Description Default
schema Dict[str, Dict[str, Any]]

Mapping from field name to its rule spec dict.

required

Returns:

Type Description
Dict[str, List[Validator]]

A validators map suitable for

Dict[str, List[Validator]]
Example
rules_from_schema({
    "name": {"required": True, "min_length": 2},
    "email": {"email": True},
})

a11y_control_attrs

a11y_control_attrs(field: FieldState, *, described_by_id: Optional[str] = None) -> Dict[str, Any]

Return ARIA attributes for an input or select control bound to a field.

  • aria-invalid is set to "true" when the field currently has an error, otherwise "false".
  • aria-describedby references described_by_id when an error is present, allowing screen readers to announce the message.

Parameters:

Name Type Description Default
field FieldState

Bound FieldState.

required
described_by_id Optional[str]

Optional id of the element rendered by error_message_attrs.

None

Returns:

Type Description
Dict[str, Any]

Props dict to spread onto the control.

error_message_attrs

error_message_attrs(*, id: str) -> Dict[str, Any]

Return attributes for an accessible error-message container.

The container becomes a polite live region so that updates are announced to assistive technology without interrupting the user.

Parameters:

Name Type Description Default
id str

DOM id to assign to the error container. Pair with a11y_control_attrs so the input references this element via aria-describedby.

required

Returns:

Type Description
Dict[str, Any]

Props dict to spread onto the error container element.

Additional helpers introduced:

  • validate_field
  • validate_form
  • on_submit_validated
  • rules_from_schema
  • a11y_control_attrs
  • error_message_attrs

Schema-based rules

rules_from_schema(schema: Dict[str, Dict[str, Any]]) -> Dict[str, List[Validator]]

Build a validators map from a lightweight schema. Supported per-field keys:

  • required: bool or str (custom message)
  • min_length: int (optional min_length_message)
  • max_length: int (optional max_length_message)
  • email: bool or str (custom message)

Example:

schema = {
    "name": {"required": True, "min_length": 2},
    "email": {"email": True},
}
rules = rules_from_schema(schema)