About me

Coding since 2018

Working at Cruncher

Mother tongue Turkish

Happy Django & HTMX user

Living in Lausanne

Formerly a tour guide

Also used Rails, Hugo, Vue etc.

Halit ÇELIK

What is HTMX?

Dependency free JS library

Adds interactivity with html attributes without writing any JS

Back-end agnostic

Extends HTML

SSE and Websockets via HTML attributes

Different approaches for web applications

Multi page applications

(traditional)

Single page applications

(modern)

HTMX approach

(mixture)

Different approaches for web applications

Multi page applications

Client

Initial request

Another request

Page reload

Server

Improved SEO

 

Easier to scale

Does not require Javascript to run

Stays in the original Hypermedia concept

Suffers from HTML restrictions

Page reloads on every request

Faster initial page load

Different approaches for web applications

Multi page applications

(Traditional)

Single page applications

(Modern)

HTMX approach

(Mixture)

Different approaches for web applications

Single page applications

Client

Initial request

Another request

Server

No page reload required

Poor SEO

 

Difficult to scale

Requires Javascript to run

Does not suffer from HTML restrictions

Page does not reload on every request

Slower initial page load

Possibility of better UX

Less secure

Better for games and 3d animations etc.

Different approaches for web applications

Multi page applications

(traditional)

Single page applications

(modern)

HTMX approach

(mixture)

Different approaches for web applications

HTMX approach

Client

Initial request

HTMX request

Server

No page reload required

HTML fragment

Does not suffer from HTML restrictions

Page does not reload on every request

Possibility of better UX

Improved SEO

 

Easier to scale

Does not require Javascript to run

Stays in the original Hypermedia concept

Faster initial page load

Not good for games etc...

How I met HTMX

<div class="row">
    <a href="{% url 'beers:edit' beer.pk %}"  
       hx-get="{% url 'beers:edit' beer.pk %}" 
       hx-target="closest .row" 
       hx-swap="outerHTML">
        <i class="ti-pencil"></i>
    </a>
</div>

Let's take a look at the example

HTMX  & Django integration

Client

HTMX  & Django integration

HTMX  & Django integration

Django Edit Object view

# Let's imagine a regular django function based view here...

def edit(request, pk):
  # This one extends base and includes the edit form.
  template = "app/edit.html"
  if request.htmx:
      #This one is just the form. Does not extend base.html
      template = "app/includes/partial.html"
  render(request, template, context)


Updating multiple places at once?

Client

HTMX request

Server

HTML fragment

HTML fragment

HTML fragment

Updating multiple places at once?

Client

HTMX request

Server

HTML fragment

HTML fragment

HTML fragment

Updating multiple places at once?

(Delete example)

<div class="row">
  <a href="{% url 'beers:delete' beer.pk %}" 
     hx-delete="{% url 'beers:delete' beer.pk %}"
     hx-target="closest .row" 
     hx-swap="outerHTML swap:.3s" 
     hx-confirm="Are you sure to delete {{beer.name}}">
     <i class="ti-close"></i>
  </a>
</div>

But... where is the CSRF token?

Updating multiple places at once?

(Delete example)

<div class="row">
  <a href="{% url 'beers:delete' beer.pk %}" 
     hx-delete="{% url 'beers:delete' beer.pk %}"
     hx-target="closest .row" 
     hx-swap="outerHTML swap:.3s" 
     hx-confirm="Are you sure to delete {{beer.name}}"
     hx-headers='{"X-CSRFToken": "{{ csrf_token }}" }'>
     <i class="ti-close"></i>
  </a>
</div>
// base.html
<script>
    document.body.addEventListener('htmx:configRequest', (event) => {
        event.detail.headers['X-CSRFToken'] = '{{ csrf_token }}';
    });
</script>

Or

Response coming from Django for delete request

<!-- The fragment that updates the message block -->
<div hx-swap-oob="true" id="messages" >
    <span> Success Very Pale Ale deleted!</span>
</div>

<!-- The fragment that updates the favourites count -->
<li hx-swap-oob="true" id="favourites-count">
    <a href="#favourites" >
        <i class="ti-heart"></i>
        <span class="favourites">1</span>
        <p class="hidden-md hidden-lg">
            favourites
            <b class="caret"></b>
        </p>
    </a>
</li>

<!-- Beer row appended to the end of table -->
<div hx-swap-oob="beforeend:#datatables">
    {% include 'beers/includes/beer-row.html' %}
</div>
<div class="card-content row" 
     hx-get="{% url 'beers:similar' beer.pk %}" 
     hx-trigger="load" 
     hx-target="this" 
     hx-swap="innerHTML">
    <img class="htmx-indicator" src="{% static 'img/indicator.svg' %}">
</div>
<input 
  placeholder="Begin Typing To Search..." 
  hx-get="{% url 'beers:active-search' %}" 
  hx-trigger="keyup changed delay:500ms" 
  hx-target="#beers-table"
  hx-push-url="true"
  hx-indicator="#indicator"
  class="form-control" 
  type="text"
  value="{{query|default:''}}"
  name="q" />

Thank you!

Resources:

Find me:

deck

By halitcelik

deck

  • 654