Skip to content

Instantly share code, notes, and snippets.

@nate-sys
Last active February 11, 2024 17:18
Show Gist options
  • Save nate-sys/59e7aed49fa780162cb29c7aef300ca7 to your computer and use it in GitHub Desktop.
Save nate-sys/59e7aed49fa780162cb29c7aef300ca7 to your computer and use it in GitHub Desktop.
Using Axum, HTMX, and DisplayDoc
[package]
name = "billion-dollar-idea"
version = "0.1.0"
edition = "2021"
[dependencies]
axum = { version = "0.7.4", features = ["macros", "form"] }
displaydoc = "0.2.4"
serde = { version = "1.0.196", features = ["derive"] }
tokio = { version = "1.36.0", features = ["full"] }
use axum::{
extract::Form,
response::Html,
routing::{get, post},
};
use displaydoc::Display;
const HTMX: &'static str = include_str!("assets/htmx.min.js");
pub trait Component: std::fmt::Display {
fn render(&self) -> Html<String> {
Html(self.to_string())
}
}
impl<T: std::fmt::Display> Component for T {}
/**
<html>
<head>
<title>Hello</title>
<script> {htmx} </script>
</head>
<body> {content} </body>
</html>
*/
#[derive(Display)]
pub struct RootComponent<C: Component> {
htmx: &'static str,
content: C,
}
impl<C: Component> RootComponent<C> {
pub fn new(content: C) -> Self {
let htmx = HTMX;
Self { htmx, content }
}
}
/**
<form
hx-post="/new"
hx-target="#list"
hx-swap="afterend"
>
<input type="text" name="name" id="name" />
</form>
<ul id="list">
</ul>
*/
#[derive(Display)]
pub struct ListComponent;
/**
<li> {title} </li>
*/
#[derive(Display)]
pub struct ItemComponent {
title: String,
}
impl ItemComponent {
pub fn new(title: &str) -> Self {
Self {
title: title.to_string(),
}
}
}
#[tokio::main]
async fn main() {
let routes = axum::Router::new()
.route("/", get(index))
.route("/new", post(add_item));
let listener = tokio::net::TcpListener::bind("127.0.0.1:3000")
.await
.unwrap();
println!("listening on {}", listener.local_addr().unwrap());
axum::serve(listener, routes).await.unwrap();
}
#[axum::debug_handler]
async fn index() -> Html<String> {
RootComponent::new(ListComponent).render()
}
#[derive(serde::Deserialize)]
pub struct ListForm {
pub name: String,
}
#[axum::debug_handler]
async fn add_item(Form(ListForm { name }): Form<ListForm>) -> Html<String> {
ItemComponent::new(&name).render()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment