pub struct Form { /* private fields */ }Expand description
Form data structure (Phase 2-A: Enhanced with client-side validation rules)
Implementations§
Source§impl Form
impl Form
Sourcepub fn new() -> Self
pub fn new() -> Self
Create a new empty form
§Examples
use reinhardt_forms::Form;
let form = Form::new();
assert!(!form.is_bound());
assert!(form.fields().is_empty());Sourcepub fn with_initial(initial: HashMap<String, Value>) -> Self
pub fn with_initial(initial: HashMap<String, Value>) -> Self
Create a new form with initial data
§Examples
use reinhardt_forms::Form;
use std::collections::HashMap;
use serde_json::json;
let mut initial = HashMap::new();
initial.insert("name".to_string(), json!("John"));
let form = Form::with_initial(initial);
assert_eq!(form.initial().get("name"), Some(&json!("John")));Sourcepub fn with_prefix(prefix: String) -> Self
pub fn with_prefix(prefix: String) -> Self
Create a new form with a field prefix
§Examples
use reinhardt_forms::Form;
let form = Form::with_prefix("user".to_string());
assert_eq!(form.prefix(), "user");
assert_eq!(form.add_prefix_to_field_name("email"), "user-email");Sourcepub fn add_field(&mut self, field: Box<dyn FormField>)
pub fn add_field(&mut self, field: Box<dyn FormField>)
Add a field to the form
§Examples
use reinhardt_forms::{Form, CharField, Field};
let mut form = Form::new();
let field = CharField::new("username".to_string());
form.add_field(Box::new(field));
assert_eq!(form.fields().len(), 1);Sourcepub fn bind(&mut self, data: HashMap<String, Value>)
pub fn bind(&mut self, data: HashMap<String, Value>)
Bind form data for validation
§Examples
use reinhardt_forms::Form;
use std::collections::HashMap;
use serde_json::json;
let mut form = Form::new();
let mut data = HashMap::new();
data.insert("username".to_string(), json!("john"));
form.bind(data);
assert!(form.is_bound());Sourcepub fn is_valid(&mut self) -> bool
pub fn is_valid(&mut self) -> bool
Validate the form and return true if all fields are valid
§Examples
use reinhardt_forms::{Form, CharField, Field};
use std::collections::HashMap;
use serde_json::json;
let mut form = Form::new();
form.add_field(Box::new(CharField::new("username".to_string())));
let mut data = HashMap::new();
data.insert("username".to_string(), json!("john"));
form.bind(data);
assert!(form.is_valid());
assert!(form.errors().is_empty());
assert_eq!(form.cleaned_data().get("username"), Some(&json!("john")));Sourcepub fn cleaned_data(&self) -> &HashMap<String, Value>
pub fn cleaned_data(&self) -> &HashMap<String, Value>
Returns the cleaned (validated) form data.
Sourcepub fn errors(&self) -> &HashMap<String, Vec<String>>
pub fn errors(&self) -> &HashMap<String, Vec<String>>
Returns the current validation errors keyed by field name.
Sourcepub fn add_error(
&mut self,
field_name: impl Into<String>,
message: impl Into<String>,
)
pub fn add_error( &mut self, field_name: impl Into<String>, message: impl Into<String>, )
Append an error message to the given field’s error list.
Use ALL_FIELDS_KEY for non-field (form-wide / cross-field) errors so
they are exposed through the same inspection API as per-field errors.
Sourcepub fn fields(&self) -> &[Box<dyn FormField>]
pub fn fields(&self) -> &[Box<dyn FormField>]
Returns the list of fields registered on this form.
Sourcepub fn initial(&self) -> &HashMap<String, Value>
pub fn initial(&self) -> &HashMap<String, Value>
Returns the initial (default) values for the form.
Sourcepub fn set_initial(&mut self, initial: HashMap<String, Value>)
pub fn set_initial(&mut self, initial: HashMap<String, Value>)
Set initial data for the form
§Examples
use reinhardt_forms::Form;
use std::collections::HashMap;
use serde_json::json;
let mut form = Form::new();
let mut initial = HashMap::new();
initial.insert("name".to_string(), json!("John"));
form.set_initial(initial);Sourcepub fn has_changed(&self) -> bool
pub fn has_changed(&self) -> bool
Check if any field has changed from its initial value
§Examples
use reinhardt_forms::{Form, CharField, Field};
use std::collections::HashMap;
use serde_json::json;
let mut initial = HashMap::new();
initial.insert("name".to_string(), json!("John"));
let mut form = Form::with_initial(initial);
form.add_field(Box::new(CharField::new("name".to_string())));
let mut data = HashMap::new();
data.insert("name".to_string(), json!("Jane"));
form.bind(data);
assert!(form.has_changed());Sourcepub fn get_field(&self, name: &str) -> Option<&dyn FormField>
pub fn get_field(&self, name: &str) -> Option<&dyn FormField>
Looks up a field by name, returning a reference if found.
Sourcepub fn remove_field(&mut self, name: &str) -> Option<Box<dyn FormField>>
pub fn remove_field(&mut self, name: &str) -> Option<Box<dyn FormField>>
Removes and returns a field by name, or None if not found.
Sourcepub fn field_count(&self) -> usize
pub fn field_count(&self) -> usize
Returns the number of fields registered on this form.
Sourcepub fn add_clean_function<F>(&mut self, f: F)
pub fn add_clean_function<F>(&mut self, f: F)
Add a custom clean function for form validation
§Examples
use reinhardt_forms::Form;
use std::collections::HashMap;
use serde_json::json;
let mut form = Form::new();
form.add_clean_function(|data| {
if data.get("password") != data.get("confirm_password") {
Err(reinhardt_forms::FormError::Validation("Passwords do not match".to_string()))
} else {
Ok(())
}
});Sourcepub fn add_field_clean_function<F>(&mut self, field_name: &str, f: F)
pub fn add_field_clean_function<F>(&mut self, field_name: &str, f: F)
Add a custom clean function for a specific field
§Examples
use reinhardt_forms::Form;
use serde_json::json;
let mut form = Form::new();
form.add_field_clean_function("email", |value| {
if let Some(email) = value.as_str() {
if email.contains("@") {
Ok(value.clone())
} else {
Err(reinhardt_forms::FormError::Validation("Invalid email".to_string()))
}
} else {
Ok(value.clone())
}
});Sourcepub fn validation_rules(&self) -> &[ValidationRule]
pub fn validation_rules(&self) -> &[ValidationRule]
Sourcepub fn add_min_length_validator(
&mut self,
field_name: impl Into<String>,
min: usize,
error_message: impl Into<String>,
)
pub fn add_min_length_validator( &mut self, field_name: impl Into<String>, min: usize, error_message: impl Into<String>, )
Add a minimum length validator (Phase 2-A)
Adds a validator that checks if a string field has at least min characters.
This validator is executed on the client-side for immediate feedback.
Security Note: Client-side validation is for UX enhancement only. Server-side validation is still mandatory for security.
§Arguments
field_name: Name of the field to validatemin: Minimum required lengtherror_message: Error message to display on validation failure
§Examples
use reinhardt_forms::Form;
let mut form = Form::new();
form.add_min_length_validator("password", 8, "Password must be at least 8 characters");Sourcepub fn add_max_length_validator(
&mut self,
field_name: impl Into<String>,
max: usize,
error_message: impl Into<String>,
)
pub fn add_max_length_validator( &mut self, field_name: impl Into<String>, max: usize, error_message: impl Into<String>, )
Add a maximum length validator (Phase 2-A)
Adds a validator that checks if a string field has at most max characters.
§Examples
use reinhardt_forms::Form;
let mut form = Form::new();
form.add_max_length_validator("username", 50, "Username must be at most 50 characters");Sourcepub fn add_pattern_validator(
&mut self,
field_name: impl Into<String>,
pattern: impl Into<String>,
error_message: impl Into<String>,
)
pub fn add_pattern_validator( &mut self, field_name: impl Into<String>, pattern: impl Into<String>, error_message: impl Into<String>, )
Add a pattern validator (Phase 2-A)
Adds a validator that checks if a string field matches a regex pattern.
§Examples
use reinhardt_forms::Form;
let mut form = Form::new();
form.add_pattern_validator("code", "^[A-Z]{3}$", "Code must be 3 uppercase letters");Sourcepub fn add_min_value_validator(
&mut self,
field_name: impl Into<String>,
min: f64,
error_message: impl Into<String>,
)
pub fn add_min_value_validator( &mut self, field_name: impl Into<String>, min: f64, error_message: impl Into<String>, )
Add a minimum value validator (Phase 2-A)
Adds a validator that checks if a numeric field is at least min.
§Examples
use reinhardt_forms::Form;
let mut form = Form::new();
form.add_min_value_validator("age", 0.0, "Age must be non-negative");Sourcepub fn add_max_value_validator(
&mut self,
field_name: impl Into<String>,
max: f64,
error_message: impl Into<String>,
)
pub fn add_max_value_validator( &mut self, field_name: impl Into<String>, max: f64, error_message: impl Into<String>, )
Add a maximum value validator (Phase 2-A)
Adds a validator that checks if a numeric field is at most max.
§Examples
use reinhardt_forms::Form;
let mut form = Form::new();
form.add_max_value_validator("age", 150.0, "Age must be at most 150");Sourcepub fn add_email_validator(
&mut self,
field_name: impl Into<String>,
error_message: impl Into<String>,
)
pub fn add_email_validator( &mut self, field_name: impl Into<String>, error_message: impl Into<String>, )
Add an email format validator (Phase 2-A)
Adds a validator that checks if a field contains a valid email format.
§Examples
use reinhardt_forms::Form;
let mut form = Form::new();
form.add_email_validator("email", "Enter a valid email address");Sourcepub fn add_url_validator(
&mut self,
field_name: impl Into<String>,
error_message: impl Into<String>,
)
pub fn add_url_validator( &mut self, field_name: impl Into<String>, error_message: impl Into<String>, )
Add a URL format validator (Phase 2-A)
Adds a validator that checks if a field contains a valid URL format.
§Examples
use reinhardt_forms::Form;
let mut form = Form::new();
form.add_url_validator("website", "Enter a valid URL");Sourcepub fn add_fields_equal_validator(
&mut self,
field_names: Vec<String>,
error_message: impl Into<String>,
target_field: Option<String>,
)
pub fn add_fields_equal_validator( &mut self, field_names: Vec<String>, error_message: impl Into<String>, target_field: Option<String>, )
Add a fields equality validator (Phase 2-A)
Adds a validator that checks if multiple fields have equal values. Commonly used for password confirmation.
§Arguments
field_names: Names of fields to compare for equalityerror_message: Error message to display on validation failuretarget_field: Target field for error display (None = non-field error)
§Examples
use reinhardt_forms::Form;
let mut form = Form::new();
form.add_fields_equal_validator(
vec!["password".to_string(), "password_confirm".to_string()],
"Passwords do not match",
Some("password_confirm".to_string())
);Sourcepub fn add_validator_rule(
&mut self,
field_name: impl Into<String>,
validator_id: impl Into<String>,
params: Value,
error_message: impl Into<String>,
)
pub fn add_validator_rule( &mut self, field_name: impl Into<String>, validator_id: impl Into<String>, params: Value, error_message: impl Into<String>, )
Add a client-side validator reference (Phase 2-A)
Adds a reference to a reinhardt-validators Validator. This validator is executed on the client-side for immediate feedback.
Security Note: Client-side validation is for UX enhancement only. Server-side validation is still mandatory for security.
§Arguments
field_name: Name of the field to validatevalidator_id: Validator identifier (e.g., “email”, “url”, “min_length”)params: Validator parameters as JSONerror_message: Error message to display on validation failure
§Examples
use reinhardt_forms::Form;
use serde_json::json;
let mut form = Form::new();
form.add_validator_rule(
"email",
"email",
json!({}),
"Enter a valid email address"
);
form.add_validator_rule(
"username",
"min_length",
json!({"min": 3}),
"Username must be at least 3 characters"
);Sourcepub fn add_date_range_validator(
&mut self,
start_field: impl Into<String>,
end_field: impl Into<String>,
error_message: Option<String>,
)
pub fn add_date_range_validator( &mut self, start_field: impl Into<String>, end_field: impl Into<String>, error_message: Option<String>, )
Helper: Add a date range validator (Phase 2-A)
Adds a validator that checks if end_date >= start_date.
§Arguments
start_field: Name of the start date fieldend_field: Name of the end date fielderror_message: Error message (optional, defaults to a standard message)
§Examples
use reinhardt_forms::Form;
let mut form = Form::new();
form.add_date_range_validator("start_date", "end_date", None);Sourcepub fn add_numeric_range_validator(
&mut self,
min_field: impl Into<String>,
max_field: impl Into<String>,
error_message: Option<String>,
)
pub fn add_numeric_range_validator( &mut self, min_field: impl Into<String>, max_field: impl Into<String>, error_message: Option<String>, )
Helper: Add a numeric range validator (Phase 2-A)
Adds a validator that checks if max >= min.
§Arguments
min_field: Name of the minimum value fieldmax_field: Name of the maximum value fielderror_message: Error message (optional, defaults to a standard message)
§Examples
use reinhardt_forms::Form;
let mut form = Form::new();
form.add_numeric_range_validator("min_price", "max_price", None);Sourcepub fn set_csrf_token(&mut self, token: String)
pub fn set_csrf_token(&mut self, token: String)
Enable CSRF protection for this form.
When enabled, is_valid() will check that the submitted data
contains a matching CSRF token.
§Arguments
token- The expected CSRF token for this form
§Examples
use reinhardt_forms::Form;
let mut form = Form::new();
form.set_csrf_token("abc123".to_string());
assert!(form.csrf_enabled());Sourcepub fn csrf_enabled(&self) -> bool
pub fn csrf_enabled(&self) -> bool
Check if CSRF protection is enabled
Sourcepub fn csrf_token(&self) -> Option<&str>
pub fn csrf_token(&self) -> Option<&str>
Get the CSRF token, if set
Sourcepub fn set_prefix(&mut self, prefix: String)
pub fn set_prefix(&mut self, prefix: String)
Sets the field name prefix for this form.
Sourcepub fn add_prefix_to_field_name(&self, field_name: &str) -> String
pub fn add_prefix_to_field_name(&self, field_name: &str) -> String
Returns the field name with the form prefix prepended (e.g., “prefix-field”).
Sourcepub fn render_css_media(&self, css_files: &[&str]) -> String
pub fn render_css_media(&self, css_files: &[&str]) -> String
Render CSS <link> tags for form media with HTML-escaped paths.
All paths are escaped using escape_attribute() to prevent XSS
via malicious CSS file paths.
§Arguments
css_files- Slice of CSS file paths to include
§Examples
use reinhardt_forms::Form;
let form = Form::new();
let html = form.render_css_media(&["/static/forms.css"]);
assert!(html.contains("href=\"/static/forms.css\""));Sourcepub fn render_js_media(&self, js_files: &[&str]) -> String
pub fn render_js_media(&self, js_files: &[&str]) -> String
Render JS <script> tags for form media with HTML-escaped paths.
All paths are escaped using escape_attribute() to prevent XSS
via malicious JS file paths.
§Arguments
js_files- Slice of JS file paths to include
§Examples
use reinhardt_forms::Form;
let form = Form::new();
let html = form.render_js_media(&["/static/forms.js"]);
assert!(html.contains("src=\"/static/forms.js\""));Sourcepub fn get_bound_field<'a>(&'a self, name: &str) -> Option<BoundField<'a>>
pub fn get_bound_field<'a>(&'a self, name: &str) -> Option<BoundField<'a>>
Returns a BoundField with the field’s submitted data and errors attached.
Source§impl Form
Safe field access by name.
impl Form
Safe field access by name.
Returns None if the field is not found instead of panicking.
§Examples
use reinhardt_forms::{Form, CharField, Field};
let mut form = Form::new();
form.add_field(Box::new(CharField::new("name".to_string())));
assert!(form.get("name").is_some());
assert!(form.get("nonexistent").is_none());