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 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()
|
||||||
|
|||||||
@@ -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/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>
|
||||||
|
|||||||
Reference in New Issue
Block a user