Reactive Partials with htmx
Better resources
- django-htmx
- Django + htmx, Luke Plant
- django-htmx-fun, Thomas Güttler
- todo, Jack Linke
- pyHAT-stack (https://github.com/PyHAT-stack/awesome-python-htmx)
General Rule: full html page
A typical class-based view (CBV):
class ContactForm(forms.Form): # (1)
...
class ContactFormView(FormView): # (2)
template_name = "pages/contact.html"
form_class = ContactForm
...
- May be contained in
forms.py
file but is joined here to illustrate a concept. - May be contained in
view.py
file but is joined here to illustrate a concept.
ContactFormView
instructs: on a GET request, render ContactForm in "pages/contact.html". Implied in this instruction: render the full html page. Django, by design, renders full pages on every request-response cycle.
Exception: partial html fragment
I deviate from the cycle by no longer rendering the full page on submission of the form. See overriden form_valid()
and form_invalid()
methods:
Both methods imply a prior POST request when a form is submitted | |
---|---|
- The default
form_invalid()
is arender_to_response()
- The default
form_valid()
is aHttpResponseRedirect()
What is rendered is a template fragment, emphasized by convention _<template_name>.html
.
How do we accomplish partial rendering of content? We need to create divisions of the html page so that we can assign parts to render.
Consider an identifiable division of the HTML page represented by id="contact-form-area"
that can be replaced without touching the other parts of the page.
htmx swapping can target the DOM node | |
---|---|
- This allows us to swap the identified element with a replacement fragment.
- Because of the identified DOM node
id="contact-form-area"
, the htmx commandhx-post
(found in the submit button of the form proper) can render a partial HTML fragment after the form is submitted and theform_valid()
function is invoked. The fragment will not affect the other parts of the page, only replacing the target#contact-form-area
.
Prompt User of Field Error on form_invalid()
On form_invalid()
, if a field error occurs, the form that is partially rendered will now contain error indicators for the specified field:
Show errors, if existing in the field | |
---|---|
- See notes on making reusable form templates.
- Only display when field contains errors.
Prompt User of Non-Field Error on form_invalid()
On form_invalid()
, if a non-field error occurs, we return the form instance like above but we include htmx-driven alerts itemizing each non-field error.
What is an example of a non-field error? Consider a login form with email
and password
fields. The user can supply a random value that is valid, i.e. an email address that is properly formatted, i.e. john@thisdoesnotexist.com However, what if that email address doesn't exist in the database? This would result in a non-field error.
In dealing with such errors, the conventional way of displaying the same is by highlighting the non-field errors above the form. See Rendering fields manually. In contrast, see Messages as Styled Notifications