Changelog¶
0.1.0a2¶
Added¶
- Documentation for six widgets that already shipped in 0.1.0a1 but were missing from the reference:
CountryInput,DatePicker,InputMask,InputNumber,OTPInput,PhoneInput.
Changed¶
- Tightened support window to Python 3.14 and Django 6.0 (was Python 3.12+ / Django 5.2+ in 0.1.0a1). Pin
django-formwork==0.1.0a1if you need the wider range.
Fixed¶
- Failed server-side searches no longer flash response body / stale prerender into the listbox. Two related fixes:
- htmx 4 (beta) changed its
noSwapdefault to[204, 304], so 4xx/5xx responses started getting swapped into the swap target — for our dropdowns that meant the Django debug HTML (or any error body) briefly painted in the listbox before ourhasErrorhandler hid it. Each dropdown's htmx-enabled input now cancels the swap onbefore:swapwhenevent.detail.ctx.response.status >= 400. - The
hasError = falsereset onbefore:requestmade the listbox visible again between request and a failed response, briefly re-showing the prerendered "No results" alert. That reset moved intobefore:swap(for status < 400 only), sohasErrornow staystrueacross consecutive failures and only clears when a successful swap actually happens.
- htmx 4 (beta) changed its
Changed¶
formwork.jsis now an ES module —{% formwork_js %}emits<script type="module" src="...">so the file's internal imports offormwork-core.jsandwidgets/*.jsresolve. Users who referenceformwork.jsdirectly (without using the template tag) must addtype="module"to their<script>tag.- Page-global core split into
formwork-core.js— the htmx morph extension, dirty-tracking, and native-validation disabling now live in their own file, loaded via the new{% formwork_core_js %}template tag.{% formwork_js %}still works exactly as before (it importsformwork-core.jsplus the three widget modules); the split lets users on{{ form.media }}load only the core they need. - Per-widget
Media.js—SearchSelect,MultiSelect, andComboBoxnow declareclass Media: js = ...so their Alpine.data component code is included automatically via{{ form.media }}. Three loading paths now coexist:{% formwork_js %}(one-tag bundle),{% formwork_core_js %}+{{ form.media }}(per-form), orimport "django-formwork/formwork.js"from a JS bundler (django-vite, webpack, esbuild). ES module URL dedup makes the paths safely composable. - Migrated to htmx 4 — The package now targets htmx 4 (currently beta). The standalone
idiomorph-ext.min.jsdependency is gone (htmx 4 has morph in core). User-facing changes:- Form templates now use
hx-swap="outerMorph"(washx-swap="morph:outerHTML"+hx-ext="morph") - Bundled examples and the e2e harness load
htmx.org@4.0.0-beta3(was@2) formwork.jsregisters aformwork-morphhtmx extension instead of monkey-patchingIdiomorph.morph()- All
hx-on::attribute event names switch from dash to colon (config-request→config:request, etc.);hx-on::send-errorconsolidates intohx-on::error htmx:afterSwap/htmx:afterSettleevent listeners renamed tohtmx:after:swap/htmx:after:settle
- Form templates now use
- Users on htmx 2 should pin the previous django-formwork version.
0.1.0a1 (2026-03-15)¶
First alpha release.
Added¶
- FormworkRenderer — Custom form renderer that applies DaisyUI-styled templates to all forms via
FORM_RENDERERsetting - FormworkForm / FormworkModelForm — Convenience base classes for per-form styling
- Form template (
formwork.html) — Renders each field inside<fieldset class="fieldset">with labels, help text, and error tooltips - Field template (
formwork_field.html) — Single source of truth for field rendering with DaisyUI tooltip errors - CSS architecture — All DaisyUI classes applied via
@applyinformwork.css(inside@layer components), not in Python or templates - Template tags —
{% formwork_css %}and{% formwork_js %}for including static assets - Custom widgets:
Toggle— Checkbox as DaisyUI toggle switchRange— HTML5 range sliderRating— Star rating with radio inputs (with optional clear button)PasswordReveal— Password input with show/hide toggle (Alpine.js)SearchSelect— Single-select dropdown with text search (static or htmx)MultiSelect— Multi-select dropdown with checkboxes (static or htmx)ComboBox— Text input with autocomplete suggestions (static or htmx, single or multiple)DataList— Text input with native<datalist>suggestionsFileDropZone— Drag-and-drop file upload with size/type validationImageDropZone— Drag-and-drop image upload with previewValidatedTextarea— Textarea with server-side validation and word highlighting
- Server-side views:
FormworkSearchView— Base view for dropdown search endpointsFormworkValidateView— Base view for textarea validation with<mark>highlighting
- htmx morph integration (
formwork.js) — Registers aformwork-morphextension that preserves Alpine.js state,<details>open state,x-text/x-htmlcontent, focused-input values, andx-for/x-ifgenerated nodes during htmx morph swaps - Django 5.2, 6.0 support; Python 3.12, 3.13, 3.14