Components / Foundations
Forms
Accessible Django field chrome and whole-form layout, with a real HTMX 422 validation loop.
Live demonstration
Use it
Read the pinned package source
- Wrap the tag in a consumer-owned form with CSRF protection and a submit control.
- For HTMX, target the form itself and re-render this same fragment on invalid input with HTTP 422.
- On valid input redirect or return a deterministic success response. Do not return a partial into a full-page non-HTMX request.
{% load i18n brickwork_forms %}
<form id="foundation-form" method="post" action="{% url 'components:foundation_form_submit' %}" hx-post="{% url 'components:foundation_form_submit' %}" hx-target="this" hx-swap="outerHTML">
{% csrf_token %}
{% bw_form form layout="grid" grid_columns=2 rows=rows density="comfortable" %}
<button class="bw-btn bw-btn--primary" type="submit">{% translate "Validate example" %}</button>
</form>
Python context
from django import forms
class ContactForm(forms.Form):
name = forms.CharField(label="Name", max_length=80)
email = forms.EmailField(label="Work email")
updates = forms.BooleanField(required=False, widget=forms.CheckboxInput(attrs={"class": "bw-toggle"}))
form = ContactForm()
rows = [["name", "email"], ["updates"]]
Public API
| Name | Signature or values | Contract |
|---|---|---|
bw_field_widget | BoundField, readonly=False | Renders one widget with input-level error and description wiring. |
bw_form | form, layout='stacked', grid_columns=2, rows=None, density='', readonly=False | Renders visible fields only. It never emits a form element. |
layout | stacked | grid | Grid preserves source and tab order. |
density | '' | compact | comfortable | spacious | A scoped form density override. |
rows | sequence[str | sequence[str]] | Groups named fields without dropping unmentioned fields. |
Accessibility and no-JavaScript behaviour
The tag associates help and error regions with the actual input. The toggle widget keeps native checkbox semantics and adds switch role only when opted in.
The form submits normally and receives a full-page response. HTMX only replaces the same form region when available.
Troubleshooting
- Errors are not announced.
- Render the same bound form fragment after validation. Do not replace only an error summary.
- An invalid HTMX response disappears.
- Keep the application's HTMX 422 responseHandling entry and return status 422.