rooting_forms/
lib.rs

1use rooting::{
2    El,
3};
4pub use rooting_forms_proc_macros::Form;
5
6pub struct FormElements {
7    /// The error display element, with `CSS_CLASS_ERROR`. This may be placed before
8    /// the label in a struct context.
9    pub error: Option<El>,
10    /// The input, and any additional controls.
11    pub elements: Vec<El>,
12}
13
14/// An object representing a form (the state of the form).
15pub trait FormState<T> {
16    /// Parse the elements into the resulting type.
17    fn parse(&self) -> Result<T, ()>;
18}
19
20/// Provides methods for creating forms from a type. All types that can appear as
21/// or within such forms must implement this. This is automatically implemented for
22/// `FormWith<()>` so if implementing yourself, focus on that trait.
23pub trait Form {
24    /// Generates a form state manager to produce form elements and parse the entered
25    /// values.
26    ///
27    /// * `field` - is the field name, for accessibility using `aria-label`. `<label>`
28    ///   isn't used sometime due to anonymous fields in tuples.
29    ///
30    /// * `from` - data used to populate the initial form, for example if creating a form
31    ///   to edit existing data.
32    fn new_form(field: &str, from: Option<&Self>) -> (FormElements, Box<dyn FormState<Self>>);
33}
34
35/// Like `Form` but allows passing in additional context, for custom elements that
36/// need it.  `FormWith<()>` is generated by the `Form` derive macro.
37pub trait FormWith<C> {
38    /// Generates a form state manager to produce form elements and parse the entered
39    /// values.
40    ///
41    /// * `context` - any additional data to be used when generating form states and
42    ///   elements. This is forwarded to all nested `new_form` calls.
43    ///
44    /// See `Form` for the other fields.
45    fn new_form_with(context: &C, field: &str, from: Option<&Self>) -> (FormElements, Box<dyn FormState<Self>>) {
46        return Self::new_form_with_(context, field, from, 0);
47    }
48    fn new_form_with_(
49        context: &C,
50        field: &str,
51        from: Option<&Self>,
52        depth: usize,
53    ) -> (FormElements, Box<dyn FormState<Self>>);
54}
55
56impl<T: FormWith<()>> Form for T {
57    fn new_form(field: &str, from: Option<&Self>) -> (FormElements, Box<dyn FormState<Self>>) {
58        return T::new_form_with(&(), field, from);
59    }
60}
61pub mod css;
62pub mod impl_str;
63pub mod impl_password;
64pub mod impl_bool;
65pub mod impl_option;
66pub mod impl_unit_structs;
67pub mod impl_vec;
68pub mod impl_macroutil;
69#[cfg(feature = "jiff")]
70pub mod impl_jiff;
71
72/// Republished types for macro use.
73pub mod republish {
74    pub use web_sys::HtmlSelectElement;
75}