blog Adding Reload to HTMX Widgets

Tags:
django htmx

I have been using htmx and django for several personal project dashboards. Instead of doing a full page load, I wanted a way to refresh individual ‘widgets’ and I think I came up with a simple way to handle it.

Intial Load

For the initial load, I have a simple section that just loads a specific widget

<section hx-get="{% url 'development:htmx-forgejo' %}" hx-trigger="load">
  <p>Forgejo</p>
</section>

Given a django URL, I have htmx do a fetch on page load.

Reload

For reloading, this is what I ended up with.

<table
  id="{{request.path|slugify}}"
  class="table table-sm table-bordered table-hover"
>
  <thead class="table-dark">
    <tr>
      <th>Forgejo ({{forgejo_list|length}})</th>
      <th>Title</th>
      <th>Repo</th>
      <th>Labels</th>
      <th>Due Date</th>
      <th>Remaining</th>
      <th>
        <details>
          <summary>Debug</summary>
          <button
            hx-get="{{request.path}}"
            hx-target="#{{request.path|slugify}}"
            hx-swap="outerHTML"
            class="badge text-bg-info"
          >
            Reload
          </button>
          <a
            class="badge text-bg-warning"
            target="_blank"
            href="{{request.path}}"
            >New Tab</a
          >
        </details>
      </th>
    </tr>
  </thead>
</table>

We first need a button that we can click to reload

<button>Reload</button>

Since we want to reload the page itself, we can easily use request.path to configure hx-get

<button hx-get="{{request.path}}">Reload</button>

We want to replace a specific target, so we can build a target based on the path, though we escape in case of weird symbols. In my case, I’m replacing a table

<table id="{{request.path|slugify}}"></table>

<button hx-get="{{request.path}}" hx-target="#{{request.path|slugify}}">
  Reload
</button>

Lastly, we want to make sure to replace the whole table to avoid weird nesting.

<table id="{{request.path|slugify}}"></table>

<button
  hx-get="{{request.path}}"
  hx-target="#{{request.path|slugify}}"
  hx-swap="outerHTML"
>
  Reload
</button>