Definitions
Waltzing templates can define Rust structs, enums, and functions that are compiled into the generated code.
@struct
Define Rust structs within templates:
Basic Struct
@struct User {
name: String,
email: String,
age: u32,
} With Derive Attributes
Add derive macros using bracket syntax:
@struct[derive(Debug, Clone, Serialize, Deserialize)] User {
name: String,
email: String,
active: bool,
}
@struct[derive(Default, PartialEq)] Config {
debug: bool,
max_items: usize,
} With Field Attributes
Add attributes to individual fields:
@struct[derive(Serialize, Deserialize)] ApiRequest {
user_id: u64,
query[serde(rename = "q")]: String,
limit[serde(default)]: Option,
secret[serde(skip_serializing)]: String,
}
@struct[derive(Deserialize)] FormData {
username: String,
password[serde(skip_serializing)]: String,
remember[serde(default = "default_false")]: bool,
} With Generics
@struct[derive(Clone)] Container {
items: Vec,
count: usize,
}
@struct[derive(Debug)] Result {
data: Option,
error: Option,
} With Lifetimes
@struct[derive(Debug)] BorrowedData<'a> {
name: &'a str,
items: &'a [Item],
} Default Derives
By default, structs automatically derive Debug, Clone, and serde::Deserialize. Disable with feature flags in Cargo.toml.
@enum
Define Rust enums within templates:
Basic Enum
@enum Status {
Active,
Inactive,
Pending,
} With Data
@enum Message {
Text(String),
Number(i64),
Pair(String, i32),
}
@enum ApiResult {
Success { data: String, count: u32 },
Error { code: u16, message: String },
Empty,
} With Derive Attributes
@enum[derive(Debug, Clone, Serialize, PartialEq)] UserRole {
Admin,
Moderator,
User,
Guest,
}
@enum[derive(Deserialize)] Action {
Create { name: String },
Update { id: u64, data: String },
Delete { id: u64 },
} With Variant Attributes
@enum[derive(Serialize, Deserialize)] Event {
Click[serde(rename = "click")] { x: i32, y: i32 },
KeyPress[serde(rename = "keypress")] { key: String },
Scroll[serde(rename = "scroll")] { delta: i32 },
} @fn (Template Functions)
Define template functions (see Components for full details):
Basic Function
@fn greet(name: String) {
Hello, @name!
} With Default Parameters
@fn button(
label: String,
variant: String = "primary",
disabled: bool = false,
) {
} With Generic Parameters
@fn list(items: &[T], class: String = "list") {
@for item in items {
- @item
}
} With Function Parameters
Pass functions as parameters for custom rendering:
@fn data_table(
items: &[T],
render_row: fn(&T) -> String,
empty_message: String = "No items",
) {
@if items.is_empty() {
@empty_message
} else {
@for item in items {
@safe((render_row)(item))
}
}
}
@* Usage *@
@data_table(users, |u| format!("{} {} ", u.name, u.email)) With Closure Parameters
@fn map_items(items: &[T], mapper: F)
where
F: Fn(&T) -> String,
{
@for item in items {
@safe((mapper)(item))
}
} @use (Imports)
Import Rust types from your crate:
@use crate::models::User
@use crate::models::{Post, Comment}
@use std::collections::HashMap
@use crate::helpers::format_date @import (Template Imports)
Import other templates:
@import "layouts/base.wtz" as layout
@import "components/button.wtz" as button
@import "components/card.wtz" as card
@fn apply(data: PageData) {
<@layout title="Home">
<@card title="Welcome">
<@button label="Click me" />
@card>
@layout>
}