egui_form/
lib.rs

1#![doc = include_str!("../README.md")]
2#![forbid(unsafe_code)]
3#![warn(missing_docs)]
4
5mod form;
6
7/// To use [garde] with `egui_form`, you need to create a [`garde::GardeReport`] and pass it to the [Form] instance.
8///
9/// Then, when you create a [`FormField`], you pass the field's name as a &str.
10/// For nested fields and arrays, the syntax for the field name looks like this:
11/// `nested.array[0].field`
12///
13/// # Example
14/// ```no_run
15/// # use eframe::NativeOptions;
16/// # use egui::CentralPanel;
17/// #
18/// # use egui_form::{Form, FormField};
19/// # use garde::Validate;
20/// # use egui_form::garde::field_path;
21///
22/// #[derive(Validate, Debug)]
23/// struct Test {
24///     #[garde(length(min = 3, max = 10))]
25///     pub user_name: String,
26///     #[garde(email)]
27///     pub email: String,
28///     #[garde(dive)]
29///     pub nested: Nested,
30///     #[garde(dive)]
31///     pub vec: Vec<Nested>,
32/// }
33///
34/// #[derive(Validate, Debug)]
35/// struct Nested {
36///     #[garde(range(min = 1, max = 10))]
37///     pub test: u64,
38/// }
39///
40/// pub fn form_ui(ui: &mut egui::Ui, test: &mut Test) {
41///     let mut form = Form::new().add_report(egui_form::garde::GardeReport::new(test.validate()));
42///
43///     FormField::new(&mut form, field_path!("user_name"))
44///         .label("User Name")
45///         .ui(ui, egui::TextEdit::singleline(&mut test.user_name));
46///     FormField::new(&mut form, field_path!("email"))
47///         .label("Email")
48///         .ui(ui, egui::TextEdit::singleline(&mut test.email));
49///     FormField::new(&mut form, field_path!("nested", "test"))
50///         .label("Nested Test")
51///         .ui(ui, egui::Slider::new(&mut test.nested.test, 0..=11));
52///     FormField::new(&mut form, field_path!("vec", 0, "test"))
53///         .label("Vec Test")
54///         .ui(
55///             ui,
56///             egui::DragValue::new(&mut test.vec[0].test).clamp_range(0..=11),
57///         );
58///
59///     if let Some(Ok(())) = form.handle_submit(&ui.button("Submit"), ui) {
60///         println!("Form submitted: {:?}", test);
61///     }
62/// }
63/// ```
64#[cfg(feature = "validator_garde")]
65pub mod garde;
66mod validation_report;
67
68mod form_field;
69/// To use [validator] with `egui_form`, you need to create a [`validator::ValidatorReport`] and pass it to the [Form] instance.
70///
71/// Then, when you create a [`FormField`], you pass a slice of [`validator::PathItem`]s.
72/// Usually, you would use the [`field_path`!] macro to create the slice.
73/// For nested fields and arrays, the syntax for the field name looks like this:
74/// `field_path!("nested", "array", 0, "field")`
75///
76/// # Example
77/// ```no_run
78/// # // Taken 1:1 from crates/egui_form/examples/validator.rs
79/// # use eframe::NativeOptions;
80/// # use egui::CentralPanel;
81/// # use egui_form::{Form, FormField};
82/// # use validator::Validate;
83/// # use egui_form::validator::field_path;
84///
85/// #[derive(Validate, Debug)]
86/// struct Test {
87///     #[validate(length(min = 3, max = 10))]
88///     pub user_name: String,
89///     #[validate(email)]
90///     pub email: String,
91///     #[validate(nested)]
92///     pub nested: Nested,
93///     #[validate(nested)]
94///     pub vec: Vec<Nested>,
95/// }
96///
97/// #[derive(Validate, Debug)]
98/// struct Nested {
99///     #[validate(range(
100///         min = 1,
101///         max = 10,
102///         message = "Custom Message: Must be between 1 and 10"
103///     ))]
104///     pub test: u64,
105/// }
106///
107/// fn form_ui(ui: &mut egui::Ui, test: &mut Test) {
108///     let mut form = Form::new().add_report(
109///         egui_form::validator::ValidatorReport::new(test.validate()).with_translation(|error| {
110///             // Since validator doesn't have default messages, we have to provide our own
111///             if let Some(msg) = &error.message {
112///                 return msg.clone();
113///             }
114///
115///             match error.code.as_ref() {
116///                 "email" => "Invalid email".into(),
117///                 "length" => format!(
118///                     "Must be between {} and {} characters long",
119///                     error.params["min"], error.params["max"]
120///                 )
121///                 .into(),
122///                 _ => format!("Validation Failed: {}", error.code).into(),
123///             }
124///         }),
125///     );
126///
127///     FormField::new(&mut form, field_path!("user_name"))
128///         .label("User Name")
129///         .ui(ui, egui::TextEdit::singleline(&mut test.user_name));
130///     FormField::new(&mut form, field_path!("email"))
131///         .label("Email")
132///         .ui(ui, egui::TextEdit::singleline(&mut test.email));
133///     FormField::new(&mut form, field_path!("nested", "test"))
134///         .label("Nested Test")
135///         .ui(ui, egui::Slider::new(&mut test.nested.test, 0..=11));
136///     FormField::new(&mut form, field_path!("vec", 0, "test"))
137///         .label("Vec Test")
138///         .ui(
139///             ui,
140///             egui::DragValue::new(&mut test.vec[0].test).clamp_range(0..=11),
141///         );
142///
143///     if let Some(Ok(())) = form.handle_submit(&ui.button("Submit"), ui) {
144///         println!("Form submitted: {:?}", test);
145///     }
146/// }
147#[cfg(feature = "validator_validator")]
148pub mod validator;
149
150pub use form::Form;
151pub use form_field::*;
152pub use validation_report::{EguiValidationReport, IntoFieldPath};