Skip to main content

dioxus_element_plug/components/
form.rs

1use dioxus::prelude::*;
2
3// Form CSS class constants
4pub const FORM: &str = "el-form";
5pub const FORM_HORIZONTAL: &str = "el-form--horizontal";
6pub const FORM_INLINE: &str = "el-form--inline";
7
8/// Form props
9#[derive(Props, Clone, PartialEq)]
10pub struct FormProps {
11    /// Form content
12    pub children: Element,
13
14    /// Form layout direction
15    #[props(default = "horizontal".to_string())]
16    pub layout: String,
17
18    /// Label position
19    #[props(default = "right".to_string())]
20    pub label_position: String,
21
22    /// Label width in pixels
23    #[props(default = 120)]
24    pub label_width: u32,
25
26    /// Form size
27    #[props(default)]
28    pub size: Option<String>,
29
30    /// Whether to show required asterisk
31    #[props(default = true)]
32    pub show_asterisk: bool,
33
34    /// Additional CSS classes
35    #[props(default)]
36    pub class: Option<String>,
37
38    /// Inline styles
39    #[props(default)]
40    pub style: Option<String>,
41
42    /// Form submit handler
43    #[props(default)]
44    pub on_submit: Option<EventHandler<FormEvent>>,
45}
46
47/// A form component wrapper
48///
49/// This component provides a styled container for form items with consistent
50/// layout and validation state management.
51///
52/// ## Example
53///
54/// ```rust,ignore
55/// use dioxus_element_plug::components::form::Form;
56/// use dioxus_element_plug::components::form_item::FormItem;
57/// use dioxus_element_plug::components::input::{Input, InputType};
58///
59/// rsx! {
60///     Form {
61///         layout: "horizontal".to_string(),
62///         label_position: "right".to_string(),
63///         on_submit: move |_| println!("Form submitted"),
64///
65///         FormItem {
66///             label: "Name",
67///             Input {
68///                 input_type: InputType::Text,
69///                 placeholder: "Enter your name",
70///             }
71///         }
72///     }
73/// }
74/// ```
75#[component]
76pub fn Form(props: FormProps) -> Element {
77    let mut class_names = vec![FORM.to_string()];
78
79    class_names.push(format!("el-form--{}", props.layout));
80
81    if let Some(ref size) = props.size {
82        class_names.push(format!("el-form--{}", size));
83    }
84
85    if props.show_asterisk {
86        class_names.push("el-form--show-asterisk".to_string());
87    }
88
89    if let Some(ref custom_class) = props.class {
90        class_names.push(custom_class.to_string());
91    }
92
93    let class_string = class_names.join(" ");
94    let style_string = props.style.as_ref().cloned().unwrap_or_default();
95
96    let form_style = format!(
97        "--el-form-label-width: {}px; {}",
98        props.label_width,
99        style_string
100    );
101
102    rsx! {
103        form {
104            class: "{class_string}",
105            style: "{form_style}",
106            onsubmit: move |event| {
107                event.prevent_default();
108                if let Some(handler) = props.on_submit {
109                    handler.call(event);
110                }
111            },
112            {props.children}
113        }
114    }
115}