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 actix_web_lab::respond::Html;
use askama::Template; use askama::Template;
#[derive(Template)] struct User {
#[template(path = "layout.html")] name: String,
struct Index; email: String,
#[derive(Clone, Debug)]
struct Row {
foo: String,
bar: String,
baz: String,
} }
#[derive(Template)] #[derive(Template)]
#[template(path = "fragment/table.html")] #[template(path = "fragment/user/table.html")]
struct Table { struct Fragment {
table: Vec<Row>, 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("/")] #[get("/")]
async fn index() -> actix_web::Result<impl Responder> { 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")] #[get("/user")]
async fn table(req: HttpRequest) -> actix_web::Result<impl Responder> { 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") { match req.headers().get("hx-request") {
Some(_) => { Some(_) => {
// Render the hypermedia fragment. // Render the hypermedia fragment.
Ok(Html( Ok(Html(Fragment { users }.render().expect("Valid template")))
Table {
table: vec![
Row {
foo: "foo".into(),
bar: "bar".into(),
baz: "baz".into()
};
10
],
}
.render()
.expect("Valid template"),
))
} }
None => { None => {
// Render the whole document // Render the whole document
// FIXME: Render the fragment in place... Ok(Html(Document { users }.render().expect("Valid template")))
Ok(Html(Index.render().expect("Valid template")))
} }
} }
} }
@@ -66,7 +68,7 @@ async fn main() -> io::Result<()> {
.wrap(middleware::Logger::default()) .wrap(middleware::Logger::default())
.service(fs::Files::new("/static", "static").show_files_listing()) .service(fs::Files::new("/static", "static").show_files_listing())
.service(index) .service(index)
.service(table) .service(users)
}) })
.bind(("127.0.0.1", 8080))? .bind(("127.0.0.1", 8080))?
.run() .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/htmx.min.js"></script>
<script src="/static/js/script.js"></script> <script src="/static/js/script.js"></script>
<title>Hello htmx!</title> <title>{% block title %}Hello htmx!{% endblock %}</title>
{% block head %}{% endblock %}
</head> </head>
<body> <body>
<hgroup> <main id="content">
<h1>Hello htmx!</h1> {% block content %}{% endblock %}
<p>A new old way to build web applications</p> </main>
</hgroup>
<table>
<tr><td>
<button hx-get="/table" hx-target="table" hx-push-url="true">
Load data
</button>
</td></tr>
</table>
</body> </body>
</html> </html>