Skip to content

Commit

Permalink
Rename bolt hx headers and attributes
Browse files Browse the repository at this point in the history
  • Loading branch information
davegaeddert committed Feb 12, 2024
1 parent daa8627 commit e82f0ac
Show file tree
Hide file tree
Showing 5 changed files with 25 additions and 23 deletions.
20 changes: 10 additions & 10 deletions bolt-htmx/bolt/htmx/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,16 +132,16 @@ When you use the `{% htmxfragment %}` tag,
a standard `div` is output that looks like this:

```html
<div bhx-fragment="main" hx-swap="outerHTML" hx-target="this" hx-indicator="this">
<div bolt-hx-fragment="main" hx-swap="outerHTML" hx-target="this" hx-indicator="this">
{{ fragment_content }}
</div>
```

The `bhx-fragment` is a custom attribute that we've added ("F" is for "Forge"),
The `bolt-hx-fragment` is a custom attribute that we've added ("F" is for "Forge"),
but the rest are standard HTMX attributes.

When Django renders the response to an HTMX request,
it will get the `BHX-Fragment` header,
it will get the `Bolt-HX-Fragment` header,
find the fragment with that name in the template,
and render that for the response.

Expand Down Expand Up @@ -169,7 +169,7 @@ and associate buttons in that template with class methods in the view.

As an example, let's say we have a `PullRequest` model and we want users to be able to open, close, or merge it with a button.

In our template, we would use the `bhx-action` attribute to name the action:
In our template, we would use the `bolt-hx-action` attribute to name the action:

```html
{% extends "base.html" %}
Expand All @@ -187,19 +187,19 @@ In our template, we would use the `bhx-action` attribute to name the action:

{% if pullrequest.state == "open" %}
<!-- If it's open, they can close or merge it -->
<button hx-post bhx-action="close">Close</button>
<button hx-post bhx-action="merge">Merge</button>
<button hx-post bolt-hx-action="close">Close</button>
<button hx-post bolt-hx-action="merge">Merge</button>
{% else if pullrequest.state == "closed" %}
<!-- If it's closed, it can be re-opened -->
<button hx-post bhx-action="open">Open</button>
<button hx-post bolt-hx-action="open">Open</button>
{% endif %}

{% endhtmxfragment %}
</main>
{% endblock %}
```

Then in the view class, we can define methods for each HTTP method + `bhx-action`:
Then in the view class, we can define methods for each HTTP method + `bolt-hx-action`:

```python
class PullRequestDetailView(HTMXViewMixin, DetailView):
Expand Down Expand Up @@ -262,7 +262,7 @@ class PullRequestDetailView(HTMXViewMixin, DetailView):
# The queryset will apply to all actions on the view, so "permission" logic can be shared
return super().get_queryset().filter(users=self.request.user)

# You can also leave off the "bhx-action" attribute and just handle the HTTP method
# You can also leave off the "bolt-hx-action" attribute and just handle the HTTP method
def htmx_delete(self, request, *args, **kwargs):
self.object = self.get_object()

Expand Down Expand Up @@ -310,7 +310,7 @@ And then subsequent HTMX requests/actions on individual items can be handled by
<!-- Send all HTMX requests to a URL for single pull requests (works inside of a loop, or on a single detail page) -->
<h2>{{ pullrequest.title }}</h2>
<button hx-get>Refresh</button>
<button hx-post bhx-action="update">Update</button>
<button hx-post bolt-hx-action="update">Update</button>
</div>
```

Expand Down
14 changes: 7 additions & 7 deletions bolt-htmx/bolt/htmx/assets/htmx/bolthtmx.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,17 @@
var csrfToken = document.currentScript.dataset.csrftoken;

htmx.on("htmx:configRequest", function (event) {
// Custom header for BHX-Action
var actionElt = htmx.closest(event.detail.elt, "[bhx-action]");
// Custom header for Bolt-HX-Action
var actionElt = htmx.closest(event.detail.elt, "[bolt-hx-action]");
if (actionElt) {
event.detail.headers["BHX-Action"] = actionElt.getAttribute("bhx-action");
event.detail.headers["Bolt-HX-Action"] = actionElt.getAttribute("bolt-hx-action");
}

// Custom header for BHX-Fragment
var fragmentElt = htmx.closest(event.detail.elt, "[bhx-fragment]");
// Custom header for Bolt-HX-Fragment
var fragmentElt = htmx.closest(event.detail.elt, "[bolt-hx-fragment]");
if (fragmentElt) {
event.detail.headers["BHX-Fragment"] =
fragmentElt.getAttribute("bhx-fragment");
event.detail.headers["Bolt-HX-Fragment"] =
fragmentElt.getAttribute("bolt-hx-fragment");
}

// Add the CSRF token to all non-GET requests automatically
Expand Down
4 changes: 2 additions & 2 deletions bolt-htmx/bolt/htmx/jinja.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,11 @@ def parse(self, parser):

def _render_htmx_fragment(self, fragment_name, render_lazy, context, caller):
if render_lazy:
return f'<div hx-get hx-trigger="bhxLoad from:body" bhx-fragment="{fragment_name}" hx-swap="outerHTML" hx-target="this" hx-indicator="this"></div>'
return f'<div hx-get hx-trigger="bhxLoad from:body" bolt-hx-fragment="{fragment_name}" hx-swap="outerHTML" hx-target="this" hx-indicator="this"></div>'
else:
# Swap innerHTML so we can re-run hx calls inside the fragment automatically
# (render_template_fragment won't render this part of the node again, just the inner nodes)
return f'<div bhx-fragment="{fragment_name}" hx-swap="innerHTML" hx-target="this" hx-indicator="this">{caller()}</div>'
return f'<div bolt-hx-fragment="{fragment_name}" hx-swap="innerHTML" hx-target="this" hx-indicator="this">{caller()}</div>'

@staticmethod
def find_template_fragment(template: jinja2.Template, fragment_name: str):
Expand Down
8 changes: 5 additions & 3 deletions bolt-htmx/bolt/htmx/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@ def get_response(self):
response = super().get_response()
# Tell browser caching to also consider the fragment header,
# not just the url/cookie.
patch_vary_headers(response, ["HX-Request", "BHX-Fragment", "BHX-Action"])
patch_vary_headers(
response, ["HX-Request", "Bolt-HX-Fragment", "Bolt-HX-Action"]
)
return response

def get_request_handler(self):
Expand Down Expand Up @@ -65,8 +67,8 @@ def is_htmx_request(self):
@property
def htmx_fragment_name(self):
# A custom header that we pass with the {% htmxfragment %} tag
return self.request.headers.get("BHX-Fragment", "")
return self.request.headers.get("Bolt-HX-Fragment", "")

@property
def htmx_action_name(self):
return self.request.headers.get("BHX-Action", "")
return self.request.headers.get("Bolt-HX-Action", "")
2 changes: 1 addition & 1 deletion bolt-staff/bolt/admin/templates/admin/search.html
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
class="*:mb-14"
hx-get="{{ view.get_absolute_url() }}?search={{ global_search_query }}&page_size=5"
hx-trigger="bhxLoad from:body"
bhx-fragment="list">
bolt-hx-fragment="list">
</div>
{% endfor %}
</div>
Expand Down

0 comments on commit e82f0ac

Please sign in to comment.