feat: render document or fragment

This commit is contained in:
2023-05-09 22:36:59 +02:00
parent f10fc81658
commit 32f5afb10f
5 changed files with 66 additions and 53 deletions

View File

@@ -5,52 +5,54 @@ use actix_web::{get, middleware, App, HttpRequest, HttpServer, Responder};
use actix_web_lab::respond::Html;
use askama::Template;
#[derive(Template)]
#[template(path = "layout.html")]
struct Index;
#[derive(Clone, Debug)]
struct Row {
foo: String,
bar: String,
baz: String,
struct User {
name: String,
email: String,
}
#[derive(Template)]
#[template(path = "fragment/table.html")]
struct Table {
table: Vec<Row>,
#[template(path = "fragment/user/table.html")]
struct Fragment {
users: Option<Vec<User>>,
}
#[derive(Default, Template)]
#[template(path = "index.html")]
struct Document {
// TODO: This is duplicated. Reuse the Fragment struct. But how?
users: Option<Vec<User>>,
}
#[get("/")]
async fn index() -> actix_web::Result<impl Responder> {
Ok(Html(Index.render().expect("Valid template")))
let page = Document { users: None };
Ok(Html(page.render().expect("Valid template")))
}
#[get("/table")]
async fn table(req: HttpRequest) -> actix_web::Result<impl Responder> {
#[get("/user")]
async fn users(req: HttpRequest) -> actix_web::Result<impl Responder> {
let users = Some(vec![
User {
name: "Jon Doe".into(),
email: "doe@foo.baz".into(),
},
User {
name: "Jane Doe".into(),
email: "j.doe@foo.baz".into(),
},
User {
name: "Joe Doe".into(),
email: "joe.doe@foo.baz".into(),
},
]);
match req.headers().get("hx-request") {
Some(_) => {
// Render the hypermedia fragment.
Ok(Html(
Table {
table: vec![
Row {
foo: "foo".into(),
bar: "bar".into(),
baz: "baz".into()
};
10
],
}
.render()
.expect("Valid template"),
))
Ok(Html(Fragment { users }.render().expect("Valid template")))
}
None => {
// Render the whole document
// FIXME: Render the fragment in place...
Ok(Html(Index.render().expect("Valid template")))
Ok(Html(Document { users }.render().expect("Valid template")))
}
}
}
@@ -66,7 +68,7 @@ async fn main() -> io::Result<()> {
.wrap(middleware::Logger::default())
.service(fs::Files::new("/static", "static").show_files_listing())
.service(index)
.service(table)
.service(users)
})
.bind(("127.0.0.1", 8080))?
.run()

View File

@@ -1,8 +0,0 @@
<thead>
<tr><th>foo</th><th>bar</th><th>baz</th></tr>
</thead>
<tbody>
{% for row in table %}
<tr><td>{{ row.foo }}</td><td>{{ row.bar }}</td><td>{{ row.baz }}</td></tr>
{% endfor %}
</tbody>

View File

@@ -0,0 +1,7 @@
<tr><th>name</th><th>email</th></tr>
{% for user in users.as_ref().unwrap() %}
<tr>
<td>{{ user.name }}</td>
<td>{{ user.email }}</td>
</tr>
{% endfor %}

19
templates/index.html Normal file
View File

@@ -0,0 +1,19 @@
{% extends "layout.html" %}
{% block content %}
<hgroup>
<h1>Hello htmx!</h1>
<p>A new old way to build web applications</p>
</hgroup>
<table>
{% if users.is_some() %}
{% include "fragment/user/table.html" %}
{% else %}
<tr><td>
<button hx-get="/user" hx-target="table" hx-push-url="true">
Load data
</button>
</td></tr>
{% endif %}
</table>
{% endblock %}

View File

@@ -9,20 +9,13 @@
<script src="/static/js/htmx.min.js"></script>
<script src="/static/js/script.js"></script>
<title>Hello htmx!</title>
<title>{% block title %}Hello htmx!{% endblock %}</title>
{% block head %}{% endblock %}
</head>
<body>
<hgroup>
<h1>Hello htmx!</h1>
<p>A new old way to build web applications</p>
</hgroup>
<table>
<tr><td>
<button hx-get="/table" hx-target="table" hx-push-url="true">
Load data
</button>
</td></tr>
</table>
<main id="content">
{% block content %}{% endblock %}
</main>
</body>
</html>