- Add a comprehensive .gitignore to manage project files. - Create the basic project structure including Cargo.toml, LICENSE, and README.md. - Add basic project documentation.
241 lines
6.1 KiB
Markdown
241 lines
6.1 KiB
Markdown
# Views Guide
|
|
|
|
This guide provides detailed instructions on how to create and customize views in the Hostbasket application.
|
|
|
|
## Table of Contents
|
|
|
|
1. [Introduction to Tera Templates](#introduction-to-tera-templates)
|
|
2. [Template Structure](#template-structure)
|
|
3. [Creating a New View](#creating-a-new-view)
|
|
4. [Template Inheritance](#template-inheritance)
|
|
5. [Using Variables](#using-variables)
|
|
6. [Control Structures](#control-structures)
|
|
7. [Filters](#filters)
|
|
8. [Macros](#macros)
|
|
9. [Custom Functions](#custom-functions)
|
|
10. [Best Practices](#best-practices)
|
|
|
|
## Introduction to Tera Templates
|
|
|
|
Hostbasket uses [Tera](https://tera.netlify.app/) as its template engine. Tera is inspired by Jinja2 and Django templates and provides a powerful way to create dynamic HTML pages.
|
|
|
|
## Template Structure
|
|
|
|
Templates are stored in the `src/views` directory. The directory structure typically follows the application's features:
|
|
|
|
```
|
|
src/views/
|
|
├── auth/
|
|
│ ├── login.html
|
|
│ └── register.html
|
|
├── home/
|
|
│ ├── index.html
|
|
│ ├── about.html
|
|
│ └── contact.html
|
|
├── tickets/
|
|
│ ├── index.html
|
|
│ ├── new.html
|
|
│ └── show.html
|
|
├── assets/
|
|
│ ├── index.html
|
|
│ ├── create.html
|
|
│ └── detail.html
|
|
└── base.html
|
|
```
|
|
|
|
## Creating a New View
|
|
|
|
To create a new view:
|
|
|
|
1. Create a new HTML file in the appropriate directory under `src/views`
|
|
2. Use template inheritance to extend the base template
|
|
3. Add your content within the appropriate blocks
|
|
|
|
Example:
|
|
|
|
```html
|
|
{% extends "base.html" %}
|
|
|
|
{% block title %}My New Page{% endblock %}
|
|
|
|
{% block content %}
|
|
<div class="container">
|
|
<h1>Welcome to My New Page</h1>
|
|
<p>This is a custom page.</p>
|
|
</div>
|
|
{% endblock %}
|
|
```
|
|
|
|
## Template Inheritance
|
|
|
|
Tera supports template inheritance, which allows you to define a base template with common elements and extend it in child templates.
|
|
|
|
### Base Template
|
|
|
|
The base template (`base.html`) typically contains the HTML structure, header, footer, and navigation menu:
|
|
|
|
```html
|
|
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>{% block title %}Hostbasket{% endblock %}</title>
|
|
<link rel="stylesheet" href="/static/css/bootstrap.min.css">
|
|
<link rel="stylesheet" href="/static/css/styles.css">
|
|
{% block head %}{% endblock %}
|
|
</head>
|
|
<body>
|
|
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
|
|
<!-- Navigation content -->
|
|
</nav>
|
|
|
|
<main>
|
|
{% block content %}{% endblock %}
|
|
</main>
|
|
|
|
<footer class="footer mt-auto py-3 bg-light">
|
|
<!-- Footer content -->
|
|
</footer>
|
|
|
|
<script src="/static/js/bootstrap.bundle.min.js"></script>
|
|
{% block scripts %}{% endblock %}
|
|
</body>
|
|
</html>
|
|
```
|
|
|
|
### Child Template
|
|
|
|
Child templates extend the base template and override specific blocks:
|
|
|
|
```html
|
|
{% extends "base.html" %}
|
|
|
|
{% block title %}Home{% endblock %}
|
|
|
|
{% block content %}
|
|
<div class="container">
|
|
<h1>Welcome to Hostbasket</h1>
|
|
<p>This is the home page.</p>
|
|
</div>
|
|
{% endblock %}
|
|
|
|
{% block scripts %}
|
|
<script src="/static/js/home.js"></script>
|
|
{% endblock %}
|
|
```
|
|
|
|
## Using Variables
|
|
|
|
You can pass variables from your controller to the template and use them in your HTML:
|
|
|
|
### In the Controller
|
|
|
|
```rust
|
|
pub async fn index(tmpl: web::Data<Tera>) -> Result<impl Responder> {
|
|
let mut ctx = tera::Context::new();
|
|
ctx.insert("title", "Welcome to Hostbasket");
|
|
ctx.insert("user_name", "John Doe");
|
|
|
|
render_template(&tmpl, "home/index.html", &ctx)
|
|
}
|
|
```
|
|
|
|
### In the Template
|
|
|
|
```html
|
|
<h1>{{ title }}</h1>
|
|
<p>Hello, {{ user_name }}!</p>
|
|
```
|
|
|
|
## Control Structures
|
|
|
|
Tera provides various control structures for conditional rendering and iteration.
|
|
|
|
### Conditionals
|
|
|
|
```html
|
|
{% if user %}
|
|
<p>Welcome, {{ user.name }}!</p>
|
|
{% else %}
|
|
<p>Please log in.</p>
|
|
{% endif %}
|
|
```
|
|
|
|
### Loops
|
|
|
|
```html
|
|
<ul>
|
|
{% for item in items %}
|
|
<li>{{ item.name }}</li>
|
|
{% endfor %}
|
|
</ul>
|
|
|
|
{% if items is empty %}
|
|
<p>No items found.</p>
|
|
{% endif %}
|
|
```
|
|
|
|
## Filters
|
|
|
|
Filters transform the values of variables:
|
|
|
|
```html
|
|
<p>{{ user.name | upper }}</p>
|
|
<p>{{ user.bio | truncate(length=100) }}</p>
|
|
<p>{{ user.created_at | date(format="%Y-%m-%d") }}</p>
|
|
```
|
|
|
|
## Macros
|
|
|
|
Macros are reusable template fragments:
|
|
|
|
```html
|
|
{% macro input(name, value='', type='text', label='') %}
|
|
<div class="mb-3">
|
|
{% if label %}
|
|
<label for="{{ name }}" class="form-label">{{ label }}</label>
|
|
{% endif %}
|
|
<input type="{{ type }}" name="{{ name }}" id="{{ name }}" value="{{ value }}" class="form-control">
|
|
</div>
|
|
{% endmacro %}
|
|
|
|
<!-- Usage -->
|
|
{{ input(name="email", type="email", label="Email Address") }}
|
|
```
|
|
|
|
## Custom Functions
|
|
|
|
You can register custom functions in Rust and use them in your templates:
|
|
|
|
### In Rust
|
|
|
|
```rust
|
|
fn register_tera_functions(tera: &mut Tera) {
|
|
tera.register_function("format_date", format_date);
|
|
}
|
|
|
|
fn format_date(args: &HashMap<String, Value>) -> Result<Value, tera::Error> {
|
|
// Implementation
|
|
}
|
|
```
|
|
|
|
### In the Template
|
|
|
|
```html
|
|
<p>{{ format_date(date=user.created_at, format="%B %d, %Y") }}</p>
|
|
```
|
|
|
|
## Best Practices
|
|
|
|
1. **Use Template Inheritance**: Extend the base template to maintain consistency across pages.
|
|
2. **Organize Templates by Feature**: Group related templates in subdirectories.
|
|
3. **Keep Templates Simple**: Move complex logic to the controller or custom functions.
|
|
4. **Use Meaningful Variable Names**: Choose descriptive names for variables and blocks.
|
|
5. **Comment Your Templates**: Add comments to explain complex sections.
|
|
6. **Validate User Input**: Always validate and sanitize user input in the controller before passing it to the template.
|
|
7. **Use Partials for Reusable Components**: Extract common components into separate files and include them where needed.
|
|
8. **Optimize for Performance**: Minimize the use of expensive operations in templates.
|
|
9. **Test Your Templates**: Ensure that your templates render correctly with different data.
|
|
10. **Follow Accessibility Guidelines**: Make your templates accessible to all users.
|