Preface
This guide demonstrates how to display dynamic messages (e.g., notifications or alerts) in a web application using Actix Web for the backend and HTMX for seamless frontend interactions. By combining these technologies with Askama for templating, you can render server-side notifications that are swapped into the DOM without full page reloads. The example includes configuration for HTMX response handling, a reusable notification template, and Rust handlers to trigger messages based on server-side logic.
Example
HTML
base.html
<!doctype html>
<html lang="en" data-theme="autumn">
<head>
<meta
name="htmx-config"
content='{
"responseHandling":[
{"code":"204", "swap": false},
{"code":"[23]..", "swap": true},
{"code":"[45]..", "swap": true, "target": "#notifications"},
{"code":"...", "swap": true}
]
}'
/>
<meta name="title" content="" />
<meta name="description" content="" />
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>{{ page_title }}</title>
<link rel="stylesheet" type="text/css" href="/static/output.css" />
<script src="/static/htmx.min.js"></script>
<script defer src="/static/alpine.min.js"></script>
<script type="module" src="https://unpkg.com/cally"></script>
{% block head %}{% endblock %}
</head>
<body class="font-primary">
{% include "./components/navbar.html" %} {% block content %}{% endblock %} {% include "./components/footer.html" %}
</body>
</html>
notifications.html
<div x-data="{ show: true }" x-show="show" x-init="setTimeout(() => show = false, 5000)"
class="toast toast-top toast-end">
<div class="alert alert-error">
<span class="font-bold text-lg">{{message|safe}}</span>
</div>
</div>
Rust
notifications.rs
use actix_web::{HttpResponse, Result};
use askama::Template;
#[derive(Template)]
#[template(path = "notification.html")]
pub struct NotificationTemplate {
pub message: String,
}
pub async fn message_err(message: &str) -> Result<HttpResponse> {
let notification = NotificationTemplate {
message: message.into(),
};
return Ok(HttpResponse::InternalServerError()
.content_type("text/html")
.body(notification.render().unwrap()));
}
example.rs
#[post("/example-handler")]
pub async fn example_actix_web_fn() -> Result<HttpResponse> {
return message_err("this is my custom message").await;
}