Hi,
Currently, I'm learning how to render HTML templates via Tera. Here is my test case if you wish to setup the very same project in your local environment by creating a new binary crate and verify it
Cargo.toml
[package]
name = "project_01"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
tera = "1"
serde = { version = "1.0.137", features = ["derive"] }
At the same directory level as Cargo.toml I have created a directory named templates with the following two files:
index.html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Test tera</title>
<meta name="Tera_tutorial" content="Tera tutorial">
<meta name="author" content="Practice">
<link rel="stylesheet" type="text/css" href="styles.css">
<script src=""></script>
</head>
<body>
{% if users %}
<div class="div_table">
<!-- Table header -->
<div class="div_table_row">
<div class="div_table_cell div_table_header">
<p>First name</p>
</div>
<div class="div_table_cell div_table_header">
<p>Last name</p>
</div>
<div class="div_table_cell div_table_header">
<p>Email</p>
</div>
</div>
<!-- Users table content -->
{% for user in users %}
<div class="div_table_row">
<div class="div_table_cell">
<p>{{ user.first_name }}</p>
</div>
<div class="div_table_cell">
<p>{{ user.last_name }}</p>
</div>
<div class="div_table_cell">
<p>{{ user.get_email() }}</p>
</div>
</div>
{% endfor %}
</div>
{% endif %}
</body>
</html>
And its CSS file in the same directory: styles.css
@import url('https://fonts.googleapis.com/css?family=Open+Sans');
.div_table {
display: table;
border-collapse: collapse;
}
.div_table_row {
display: table-row;
}
.div_table_header {
font-weight: bold;
text-align: center;
}
.div_table_cell {
display: table-cell;
padding-left: 10px;
padding-right: 10px;
font-family: "Open Sans";
font-size: 11px;
border-top: 1px solid #000000;
}
And finally the main program : main.rs
use std::fs;
use tera::Tera;
use tera::Context;
use serde::Serialize;
#[derive(Debug, Serialize)]
struct User {
first_name: String,
last_name: String,
}
impl User {
fn get_email(&self) -> String {
format!(
"{}{}{}{}",
self.first_name,
".",
self.last_name,
"@mycorporate.com"
)
}
}
fn init() -> Result<String, tera::Error> {
// Use globbing
let tera = match Tera::new("templates/*.html") {
Ok(t) => t,
Err(e) => {
println!("Parsing error(s): {}", e);
::std::process::exit(1);
}
};
let mut users: Vec<User> = Vec::new();
users.push(User {
first_name: String::from("fname-01"),
last_name: String::from("lname-01"),
});
users.push(User {
first_name: String::from("fname-02"),
last_name: String::from("lname-02"),
});
users.push(User {
first_name: String::from("fname-03"),
last_name: String::from("lname-03"),
});
let mut context = Context::new();
context.insert("users", &users);
let result = {
tera.render("index.html", &context)?
};
Ok(result)
}
fn main() -> std::io::Result<()> {
let result = init();
match result {
Ok(value) => {
let output_file_name = "templates/result_template.html";
fs::File::create(output_file_name).unwrap();
fs::write(output_file_name, value).unwrap();
()
},
Err(e) => {
panic!("{}", e);
}
}
Ok(())
}
This fails with the following error message:
* Failed to parse "templates\\index.html"
--> 39:35
|
39 | <p>{{ user.get_email() }}</p>␍␊
| ^---
|
= expected `or`, `and`, `not`, `<=`, `>=`, `<`, `>`, `==`, `!=`, `+`, `-`, `*`, `/`, `%`, a filter, or a variable end (`}}`)
error: process didn't exit successfully: `target\debug\project_01.exe` (exit code: 1)
cargo-run exited abnormally with code 1 at Thu May 26 16:55:06
And this is the part of my HTML template that causes the error:
<div class="div_table_cell">
<p>{{ user.get_email() }}</p>
</div>
Therefore, I would like to know whether is possible to call a struct's method in Tera templates. I mean, in the above code, I can use {{ user.first_name }}
and {{ user.last_name }}
which are both defined in User
struct. So I don't understand why the method syntax on the same struct which returns an expression (String) causes a problem. Is it that in Tera it is impossible to call methods or it's me who's not writing and calling the function correctly in the template?
Thanks in advance