Skip to content

Live Validation

The LiveValidationField and ValidationMessage components wire inputs for HTMX live validation and render validation feedback.

Quick Start

LiveValidationField(
    Input("email", input_type="email"),
    validate_url="/validate/email",
    label="Email Address",
)

Usage Scenarios

With Validation Endpoint

LiveValidationField(
    Input("username", value=""),
    validate_url="/validate/username",
    label="Username",
    help_text="Must be unique",
)

Validation Message Fragment

ValidationMessage("Username is available", state="valid")
ValidationMessage("Username is taken", state="invalid")

With Indicator

LiveValidationField(
    Input("promo_code"),
    validate_url="/validate/promo",
    label="Promo Code",
    indicator="#spinner",
)

Parameter Reference

LiveValidationField

Parameter Type Default Description
input_element Any Required Input, Select, or Textarea component
validate_url str Required Validation endpoint URL
label str \| None None Label text
help_text str \| None None Help text below input
error str \| None None Error message
success str \| None None Success message
is_invalid bool False Whether to show invalid state
is_valid bool False Whether to show valid state
required bool False Mark as required
method "get" \| "post" "post" Validation request method
trigger str "blur changed delay:300ms" HTMX trigger
target str "closest .mb-3" HTMX target
swap str "outerHTML" HTMX swap style
indicator str \| None None HTMX indicator selector
**kwargs Any - Additional HTML attributes

ValidationMessage

Parameter Type Default Description
message str \| None Required Message to display
state "invalid" \| "valid" \| "neutral" "invalid" Validation state
**kwargs Any - Additional HTML attributes

Accessibility

  • Validation messages use semantic invalid-feedback and valid-feedback classes.
  • Inputs retain their native aria attributes.
  • Help text is preserved via aria-describedby.

API Reference

faststrap.components.forms.errors.LiveValidationField(input_element, validate_url, *, label=None, help_text=None, error=None, success=None, is_invalid=False, is_valid=False, required=False, method='post', trigger='blur changed delay:300ms', target='closest .mb-3', swap='outerHTML', indicator=None, **kwargs)

FormGroup wrapper that wires an input for HTMX live validation.

The validation endpoint should return a replacement FormGroup or another fragment compatible with the configured hx_target/hx_swap.

Source code in src/faststrap/components/forms/errors.py
@register(category="forms")
def LiveValidationField(
    input_element: Any,
    validate_url: str,
    *,
    label: str | None = None,
    help_text: str | None = None,
    error: str | None = None,
    success: str | None = None,
    is_invalid: bool = False,
    is_valid: bool = False,
    required: bool = False,
    method: Literal["get", "post"] = "post",
    trigger: str = "blur changed delay:300ms",
    target: str = "closest .mb-3",
    swap: str = "outerHTML",
    indicator: str | None = None,
    **kwargs: Any,
) -> Any:
    """FormGroup wrapper that wires an input for HTMX live validation.

    The validation endpoint should return a replacement `FormGroup` or another
    fragment compatible with the configured `hx_target`/`hx_swap`.
    """
    if hasattr(input_element, "attrs"):
        if method == "get":
            input_element.attrs["hx-get"] = validate_url
        else:
            input_element.attrs["hx-post"] = validate_url
        input_element.attrs["hx-trigger"] = trigger
        input_element.attrs["hx-target"] = target
        input_element.attrs["hx-swap"] = swap
        if indicator:
            input_element.attrs["hx-indicator"] = indicator

    return FormGroup(
        input_element,
        label=label,
        help_text=help_text,
        error=error,
        success=success,
        is_invalid=is_invalid,
        is_valid=is_valid,
        required=required,
        **kwargs,
    )

faststrap.components.forms.errors.ValidationMessage(message, *, state='invalid', **kwargs)

Render a Bootstrap-compatible validation feedback message.

This is useful for HTMX live validation endpoints that return only the small feedback fragment for one field.

Source code in src/faststrap/components/forms/errors.py
@register(category="forms")
def ValidationMessage(
    message: str | None,
    *,
    state: Literal["invalid", "valid", "neutral"] = "invalid",
    **kwargs: Any,
) -> Div | None:
    """Render a Bootstrap-compatible validation feedback message.

    This is useful for HTMX live validation endpoints that return only the
    small feedback fragment for one field.
    """
    if not message:
        return None

    cls = kwargs.pop("cls", "")
    state_cls = {
        "invalid": "invalid-feedback d-block",
        "valid": "valid-feedback d-block",
        "neutral": "form-text text-muted",
    }[state]
    attrs: dict[str, Any] = {"cls": f"{state_cls} {cls}".strip()}
    attrs.update(convert_attrs(kwargs))
    return Div(message, **attrs)