feat: render document or fragment
This commit is contained in:
66
src/main.rs
66
src/main.rs
@@ -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()
|
||||
|
||||
@@ -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>
|
||||
7
templates/fragment/user/table.html
Normal file
7
templates/fragment/user/table.html
Normal 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
19
templates/index.html
Normal 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 %}
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user