rust 54 lines · 8 steps

Building an HTMX-aware toggle handler in Axum

An Axum handler flips a todo's completed state in Postgres and returns either an HTML fragment or a full page depending on the caller.

Explained by highlit
1use axum::{
2 extract::{Path, State},
3 http::HeaderMap,
4 response::{Html, IntoResponse},
5};
6 
7pub async fn toggle_todo(
8 State(pool): State<PgPool>,
9 headers: HeaderMap,
10 Path(id): Path<i64>,
11) -> Result<impl IntoResponse, AppError> {
12 let todo = sqlx::query_as!(
13 Todo,
14 r#"
15 UPDATE todos
16 SET completed = NOT completed, updated_at = now()
17 WHERE id = $1
18 RETURNING id, title, completed
19 "#,
20 id
21 )
22 .fetch_one(&pool)
23 .await?;
24 
25 let is_htmx = headers
26 .get("HX-Request")
27 .map(|v| v == "true")
28 .unwrap_or(false);
29 
30 if is_htmx {
31 return Ok(Html(render_todo_row(&todo)));
32 }
33 
34 let remaining = sqlx::query_scalar!("SELECT count(*) FROM todos WHERE NOT completed")
35 .fetch_one(&pool)
36 .await?
37 .unwrap_or(0);
38 
39 Ok(Html(render_full_page(&todo, remaining)))
40}
41 
42fn render_todo_row(todo: &Todo) -> String {
43 let checked = if todo.completed { "checked" } else { "" };
44 format!(
45 r#"<li id="todo-{id}" class="todo {class}">
46 <input type="checkbox" hx-post="/todos/{id}/toggle" hx-target="#todo-{id}" hx-swap="outerHTML" {checked}>
47 <span>{title}</span>
48</li>"#,
49 id = todo.id,
50 class = if todo.completed { "done" } else { "" },
51 title = askama_escape::escape(&todo.title, askama_escape::Html),
52 checked = checked,
53 )
54}
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1Axum extractors let you declare exactly which parts of a request a handler needs, right in the signature.
  2. 2Inspecting a request header lets one endpoint serve both progressive-enhancement fragments and full pages.
  3. 3Compile-time-checked SQL macros keep the UPDATE and its returned struct in sync with the database schema.

Related explainers

Share this explainer

Here's the card — post it anywhere.

Building an HTMX-aware toggle handler in Axum — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code