]> git.proxmox.com Git - ui/proxmox-yew-widget-toolkit.git/commitdiff
widget: form: rename Boolean to Checkbox
authorDominik Csapak <d.csapak@proxmox.com>
Mon, 30 Sep 2024 11:22:41 +0000 (13:22 +0200)
committerDietmar Maurer <dietmar@proxmox.com>
Mon, 30 Sep 2024 12:24:59 +0000 (14:24 +0200)
and remove old `Checkbox` implementation. Since we now have a separate
RadioButton component and the Boolean one has more features that should
cover all use cases of the old Checkbox field, simply rename the Boolean
to Checkbox.

Also having only one Checkbox component  instead of two separate ones is
less confusing and less error prone.

This makes it necessary to adapt all code paths using either Checkbox or
Boolean, but these changes should be rather trivial:
* either changing the submit_on/off_values where we used a checkbox
  previously
* or rename Boolean to Checkbox

If we missed some use case for the Checkbox, we can either simply add it
again, or use a more generic Field with input_type 'checkbox' instead.

Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
src/widget/form/boolean.rs [deleted file]
src/widget/form/checkbox.rs
src/widget/form/context.rs
src/widget/form/mod.rs

diff --git a/src/widget/form/boolean.rs b/src/widget/form/boolean.rs
deleted file mode 100644 (file)
index a4eb5c2..0000000
+++ /dev/null
@@ -1,357 +0,0 @@
-use anyhow::Error;
-use serde_json::Value;
-
-use yew::html::{IntoEventCallback, IntoPropValue};
-use yew::prelude::*;
-
-use pwt_macros::{builder, widget};
-
-use super::{
-    IntoValidateFn, ManagedField, ManagedFieldContext, ManagedFieldMaster, ManagedFieldState,
-    ValidateFn,
-};
-use crate::css::AlignItems;
-use crate::props::{ContainerBuilder, CssPaddingBuilder, EventSubscriber, WidgetBuilder};
-use crate::tr;
-use crate::widget::{Container, Fa, FieldLabel, Row, Tooltip};
-
-pub type PwtBoolean = ManagedFieldMaster<BooleanField>;
-
-/// Checkbox input element, which stores values as boolean
-#[widget(pwt=crate, comp=ManagedFieldMaster<BooleanField>, @input, @element)]
-#[derive(Clone, PartialEq, Properties)]
-#[builder]
-pub struct Boolean {
-    /// The value that will be submitted when the field is checked/on.
-    ///
-    /// Note: must differ from the `submit_off_value` to be working correctly.
-    #[builder(Into, into)]
-    #[prop_or(Value::Bool(true))]
-    pub submit_on_value: Value,
-
-    /// The value that will be submitted when the field is not checked/off.
-    ///
-    /// Note: must differ from the `submit_on_value` to be working correctly.
-    #[builder(Into, into)]
-    #[prop_or(Value::Bool(false))]
-    pub submit_off_value: Value,
-
-    /// Force value (ignored by managed fields)
-    #[builder(IntoPropValue, into_prop_value)]
-    #[prop_or_default]
-    pub checked: Option<bool>,
-
-    /// Default value.
-    #[builder(IntoPropValue, into_prop_value)]
-    #[prop_or_default]
-    pub default: Option<bool>,
-
-    /// Use switch style layout.
-    #[prop_or_default]
-    #[builder]
-    pub switch: bool,
-
-    /// The tooltip.
-    #[prop_or_default]
-    #[builder(IntoPropValue, into_prop_value)]
-    pub tip: Option<AttrValue>,
-
-    /// Validation function.
-    ///
-    /// ```
-    /// # use anyhow::bail;
-    /// # use pwt::prelude::*;
-    /// # use pwt::widget::form::Boolean;
-    /// Boolean::new()
-    ///   .submit(false)
-    ///   .validate(|value: &bool| {
-    ///      if !value {
-    ///         bail!("Please accept the Terms Of Service")
-    ///      }
-    ///      Ok(())
-    ///    });
-    /// ```
-    #[prop_or_default]
-    pub validate: Option<ValidateFn<bool>>,
-
-    /// Change callback
-    #[builder_cb(IntoEventCallback, into_event_callback, bool)]
-    #[prop_or_default]
-    pub on_change: Option<Callback<bool>>,
-
-    /// Input callback.
-    ///
-    /// Called on user interaction:
-    ///
-    /// - Click on the checkbox.
-    /// - Click on the associated input label.
-    /// - Activation by keyboard (space press).
-    #[builder_cb(IntoEventCallback, into_event_callback, bool)]
-    #[prop_or_default]
-    pub on_input: Option<Callback<bool>>,
-
-    /// A right side label for the checkbox, to display additional information
-    #[prop_or_default]
-    pub box_label: Option<FieldLabel>,
-}
-
-impl Boolean {
-    /// Creates a new instance.
-    pub fn new() -> Self {
-        yew::props!(Self {})
-    }
-
-    /// Builder style method to set the validate callback
-    pub fn validate(mut self, validate: impl IntoValidateFn<bool>) -> Self {
-        self.set_validate(validate);
-        self
-    }
-
-    /// Method to set the validate callback
-    pub fn set_validate(&mut self, validate: impl IntoValidateFn<bool>) {
-        self.validate = validate.into_validate_fn();
-    }
-
-    /// Method to set the box label.
-    ///
-    /// A right side label for the checkbox to display additional information
-    pub fn set_box_label(&mut self, box_label: impl Into<FieldLabel>) {
-        self.box_label = Some(box_label.into());
-    }
-
-    /// Builder method to set the box label.
-    ///
-    ///A right side label for the checkbox to display additional information
-    pub fn box_label(mut self, box_label: impl Into<FieldLabel>) -> Self {
-        self.set_box_label(box_label);
-        self
-    }
-}
-pub enum Msg {
-    Toggle,
-}
-
-#[doc(hidden)]
-pub struct BooleanField {}
-
-#[derive(PartialEq)]
-pub struct ValidateClosure {
-    validate: Option<ValidateFn<bool>>,
-    submit_on_value: Value,
-    submit_off_value: Value,
-}
-
-impl ManagedField for BooleanField {
-    type Properties = Boolean;
-    type Message = Msg;
-    type ValidateClosure = ValidateClosure;
-
-    fn validation_args(props: &Self::Properties) -> Self::ValidateClosure {
-        ValidateClosure {
-            validate: props.validate.clone(),
-            submit_on_value: props.submit_on_value.clone(),
-            submit_off_value: props.submit_off_value.clone(),
-        }
-    }
-
-    fn validator(props: &Self::ValidateClosure, value: &Value) -> Result<Value, Error> {
-        let value = match value {
-            Value::Bool(value) => *value,
-            other => {
-                if *other == props.submit_on_value {
-                    true
-                } else if *other == props.submit_off_value {
-                    false
-                } else {
-                    return Err(Error::msg(tr!("got invalid value.")));
-                }
-            }
-        };
-
-        if let Some(validate) = &props.validate {
-            validate.apply(&value)?;
-        }
-
-        Ok(Value::Bool(value))
-    }
-
-    fn setup(props: &Boolean) -> ManagedFieldState {
-        let mut value = Value::Bool(false);
-        if let Some(default) = &props.default {
-            value = if *default {
-                props.submit_on_value.clone()
-            } else {
-                props.submit_off_value.clone()
-            };
-        }
-        if let Some(checked) = &props.checked {
-            value = if *checked {
-                props.submit_on_value.clone()
-            } else {
-                props.submit_off_value.clone()
-            };
-        }
-
-        let valid = Ok(());
-
-        let default = if props.default.unwrap_or(false) {
-            props.submit_on_value.clone()
-        } else {
-            props.submit_off_value.clone()
-        };
-
-        ManagedFieldState {
-            value,
-            valid,
-            default,
-            radio_group: false,
-            unique: false,
-        }
-    }
-
-    fn create(_ctx: &ManagedFieldContext<Self>) -> Self {
-        Self {}
-    }
-
-    fn label_clicked(&mut self, ctx: &ManagedFieldContext<Self>) -> bool {
-        ctx.link().send_message(Msg::Toggle);
-        false
-    }
-
-    fn update(&mut self, ctx: &ManagedFieldContext<Self>, msg: Self::Message) -> bool {
-        let props = ctx.props();
-        let state = ctx.state();
-        match msg {
-            Msg::Toggle => {
-                if props.input_props.disabled {
-                    return true;
-                }
-                let checked = state.value == props.submit_on_value;
-                let new_value = if checked {
-                    props.submit_off_value.clone()
-                } else {
-                    props.submit_on_value.clone()
-                };
-                ctx.link().update_value(new_value);
-
-                if let Some(on_input) = &props.on_input {
-                    on_input.emit(!checked);
-                }
-
-                false
-            }
-        }
-    }
-
-    fn value_changed(&mut self, ctx: &ManagedFieldContext<Self>) {
-        let props = ctx.props();
-        let state = ctx.state();
-        let checked = state.value == props.submit_on_value;
-        if let Some(on_change) = &props.on_change {
-            on_change.emit(checked);
-        }
-    }
-
-    fn changed(&mut self, ctx: &ManagedFieldContext<Self>, _old_props: &Self::Properties) -> bool {
-        let props = ctx.props();
-        if let Some(checked) = props.checked {
-            let value = if checked {
-                props.submit_on_value.clone()
-            } else {
-                props.submit_off_value.clone()
-            };
-            ctx.link().force_value(Some(value), None)
-        }
-        true
-    }
-
-    fn view(&self, ctx: &ManagedFieldContext<Self>) -> Html {
-        let props = ctx.props();
-        let link = ctx.link();
-        let disabled = props.input_props.disabled;
-
-        let state = ctx.state();
-
-        let (value, valid) = (&state.value, &state.valid);
-        let checked = {
-            let this = &props;
-            *value == this.submit_on_value
-        };
-
-        let onclick = link.callback(|_| Msg::Toggle);
-        let onkeyup = Callback::from({
-            let link = link.clone();
-            move |event: KeyboardEvent| {
-                if event.key() == " " {
-                    link.send_message(Msg::Toggle);
-                }
-            }
-        });
-
-        let (layout_class, inner_class) = match props.switch {
-            true => ("pwt-switch", "pwt-switch-slider"),
-            false => ("pwt-checkbox", "pwt-checkbox-icon"),
-        };
-
-        let checkbox = Container::new()
-            .class((!props.switch).then_some("pwt-checkbox-state"))
-            .with_child(
-                Container::new()
-                    .class(layout_class)
-                    .with_child(
-                        Container::from_tag("span")
-                            .class(inner_class)
-                            .with_child(Fa::new("check")),
-                    )
-                    .class(checked.then_some("checked"))
-                    .class(disabled.then_some("disabled"))
-                    .class(if valid.is_ok() {
-                        "is-valid"
-                    } else {
-                        "is-invalid"
-                    })
-                    .attribute(
-                        "tabindex",
-                        props.input_props.tabindex.unwrap_or(0).to_string(),
-                    )
-                    .attribute("role", "checkbox")
-                    .attribute("aria-checked", checked.then_some("true"))
-                    .onkeyup(onkeyup),
-            );
-
-        let box_label = props.box_label.clone().map(|label| label.padding_start(2));
-
-        let checkbox = Row::new()
-            .class(AlignItems::Center)
-            .with_child(checkbox)
-            .with_optional_child(box_label);
-
-        // TODO: add other props.input_props
-
-        let mut checkbox = Tooltip::new(checkbox)
-            .with_std_props(&props.std_props)
-            .listeners(&props.listeners)
-            .onclick(onclick);
-
-        if let Err(msg) = &valid {
-            checkbox.set_tip(msg.clone())
-        } else if let Some(tip) = &props.tip {
-            if !disabled {
-                checkbox.set_tip(tip.clone())
-            }
-        }
-
-        checkbox.into()
-    }
-
-    fn rendered(&mut self, ctx: &ManagedFieldContext<Self>, first_render: bool) {
-        if first_render {
-            let props = ctx.props();
-            if props.input_props.autofocus {
-                if let Some(el) = props.std_props.node_ref.cast::<web_sys::HtmlElement>() {
-                    let _ = el.focus();
-                }
-            }
-        }
-    }
-}
index b17c6c6208d2ab8df77eaba6b91d530acdd51dbb..cf4069069432563454f7dc69f14cee37d79c7c20 100644 (file)
@@ -6,28 +6,37 @@ use yew::prelude::*;
 
 use pwt_macros::{builder, widget};
 
-use crate::props::{ContainerBuilder, EventSubscriber, WidgetBuilder};
-use crate::tr;
-use crate::widget::{Container, Tooltip};
-
 use super::{
     IntoValidateFn, ManagedField, ManagedFieldContext, ManagedFieldMaster, ManagedFieldState,
     ValidateFn,
 };
+use crate::css::AlignItems;
+use crate::props::{ContainerBuilder, CssPaddingBuilder, EventSubscriber, WidgetBuilder};
+use crate::tr;
+use crate::widget::{Container, Fa, FieldLabel, Row, Tooltip};
 
 pub type PwtCheckbox = ManagedFieldMaster<CheckboxField>;
 
-/// Checkbox input element.
+/// Checkbox input element, which stores values as boolean
 #[widget(pwt=crate, comp=ManagedFieldMaster<CheckboxField>, @input, @element)]
 #[derive(Clone, PartialEq, Properties)]
 #[builder]
 pub struct Checkbox {
-    /// Checkbox value (default is "on").
-    #[builder(IntoPropValue, into_prop_value)]
-    #[prop_or_default]
-    pub value: Option<AttrValue>,
+    /// The value that will be submitted when the field is checked/on.
+    ///
+    /// Note: must differ from the `submit_off_value` to be working correctly.
+    #[builder(Into, into)]
+    #[prop_or(Value::Bool(true))]
+    pub submit_on_value: Value,
+
+    /// The value that will be submitted when the field is not checked/off.
+    ///
+    /// Note: must differ from the `submit_on_value` to be working correctly.
+    #[builder(Into, into)]
+    #[prop_or(Value::Bool(false))]
+    pub submit_off_value: Value,
 
-    /// Force value (ignored by managed fields).
+    /// Force value (ignored by managed fields)
     #[builder(IntoPropValue, into_prop_value)]
     #[prop_or_default]
     pub checked: Option<bool>,
@@ -37,11 +46,6 @@ pub struct Checkbox {
     #[prop_or_default]
     pub default: Option<bool>,
 
-    /// Radio group flag
-    #[prop_or_default]
-    #[builder]
-    pub radio_group: bool,
-
     /// Use switch style layout.
     #[prop_or_default]
     #[builder]
@@ -70,10 +74,10 @@ pub struct Checkbox {
     #[prop_or_default]
     pub validate: Option<ValidateFn<bool>>,
 
-    /// Change callback.
-    #[builder_cb(IntoEventCallback, into_event_callback, String)]
+    /// Change callback
+    #[builder_cb(IntoEventCallback, into_event_callback, bool)]
     #[prop_or_default]
-    pub on_change: Option<Callback<String>>,
+    pub on_change: Option<Callback<bool>>,
 
     /// Input callback.
     ///
@@ -82,9 +86,13 @@ pub struct Checkbox {
     /// - Click on the checkbox.
     /// - Click on the associated input label.
     /// - Activation by keyboard (space press).
-    #[builder_cb(IntoEventCallback, into_event_callback, String)]
+    #[builder_cb(IntoEventCallback, into_event_callback, bool)]
+    #[prop_or_default]
+    pub on_input: Option<Callback<bool>>,
+
+    /// A right side label for the checkbox, to display additional information
     #[prop_or_default]
-    pub on_input: Option<Callback<String>>,
+    pub box_label: Option<FieldLabel>,
 }
 
 impl Checkbox {
@@ -93,11 +101,6 @@ impl Checkbox {
         yew::props!(Self {})
     }
 
-    /// Creates a radio group member.
-    pub fn radio() -> Self {
-        yew::props!(Self { radio_group: true })
-    }
-
     /// Builder style method to set the validate callback
     pub fn validate(mut self, validate: impl IntoValidateFn<bool>) -> Self {
         self.set_validate(validate);
@@ -108,8 +111,22 @@ impl Checkbox {
     pub fn set_validate(&mut self, validate: impl IntoValidateFn<bool>) {
         self.validate = validate.into_validate_fn();
     }
-}
 
+    /// Method to set the box label.
+    ///
+    /// A right side label for the checkbox to display additional information
+    pub fn set_box_label(&mut self, box_label: impl Into<FieldLabel>) {
+        self.box_label = Some(box_label.into());
+    }
+
+    /// Builder method to set the box label.
+    ///
+    ///A right side label for the checkbox to display additional information
+    pub fn box_label(mut self, box_label: impl Into<FieldLabel>) -> Self {
+        self.set_box_label(box_label);
+        self
+    }
+}
 pub enum Msg {
     Toggle,
 }
@@ -120,70 +137,78 @@ pub struct CheckboxField {}
 #[derive(PartialEq)]
 pub struct ValidateClosure {
     validate: Option<ValidateFn<bool>>,
-    on_value: AttrValue,
+    submit_on_value: Value,
+    submit_off_value: Value,
 }
 
 impl ManagedField for CheckboxField {
-    type Message = Msg;
     type Properties = Checkbox;
+    type Message = Msg;
     type ValidateClosure = ValidateClosure;
 
     fn validation_args(props: &Self::Properties) -> Self::ValidateClosure {
         ValidateClosure {
             validate: props.validate.clone(),
-            on_value: props.value.clone().unwrap_or(AttrValue::Static("on")),
+            submit_on_value: props.submit_on_value.clone(),
+            submit_off_value: props.submit_off_value.clone(),
         }
     }
 
     fn validator(props: &Self::ValidateClosure, value: &Value) -> Result<Value, Error> {
         let value = match value {
-            Value::String(value) => value == &props.on_value,
-            _ => return Err(Error::msg(tr!("got wrong data type."))),
+            Value::Bool(value) => *value,
+            other => {
+                if *other == props.submit_on_value {
+                    true
+                } else if *other == props.submit_off_value {
+                    false
+                } else {
+                    return Err(Error::msg(tr!("got invalid value.")));
+                }
+            }
         };
 
         if let Some(validate) = &props.validate {
             validate.apply(&value)?;
         }
 
-        Ok(if value {
-            Value::String(props.on_value.to_string())
-        } else {
-            Value::String(String::new())
-        })
+        Ok(Value::Bool(value))
     }
 
     fn setup(props: &Checkbox) -> ManagedFieldState {
-        let on_value = props.value.as_deref().unwrap_or("on").to_string();
+        let mut value = Value::Bool(false);
+        if let Some(default) = &props.default {
+            value = if *default {
+                props.submit_on_value.clone()
+            } else {
+                props.submit_off_value.clone()
+            };
+        }
+        if let Some(checked) = &props.checked {
+            value = if *checked {
+                props.submit_on_value.clone()
+            } else {
+                props.submit_off_value.clone()
+            };
+        }
 
-        let default = match props.default {
-            Some(true) => on_value.clone(),
-            _ => String::new(),
-        };
+        let valid = Ok(());
 
-        let value = match props.checked {
-            Some(true) => on_value.clone(),
-            Some(false) => String::new(),
-            None => default.clone(),
+        let default = if props.default.unwrap_or(false) {
+            props.submit_on_value.clone()
+        } else {
+            props.submit_off_value.clone()
         };
 
         ManagedFieldState {
-            value: value.into(),
-            valid: Ok(()),
-            default: default.into(),
-            radio_group: props.radio_group,
+            value,
+            valid,
+            default,
+            radio_group: false,
             unique: false,
         }
     }
 
-    fn value_changed(&mut self, ctx: &super::ManagedFieldContext<Self>) {
-        let props = ctx.props();
-        let state = ctx.state();
-        let value = state.value.as_str().unwrap_or("").to_string();
-        if let Some(on_change) = &props.on_change {
-            on_change.emit(value);
-        }
-    }
-
     fn create(_ctx: &ManagedFieldContext<Self>) -> Self {
         Self {}
     }
@@ -196,64 +221,66 @@ impl ManagedField for CheckboxField {
     fn update(&mut self, ctx: &ManagedFieldContext<Self>, msg: Self::Message) -> bool {
         let props = ctx.props();
         let state = ctx.state();
-
         match msg {
             Msg::Toggle => {
                 if props.input_props.disabled {
                     return true;
                 }
-                let on_value = props.value.as_deref().unwrap_or("on").to_string();
-                let value = state.value.clone();
-                let new_value = if value == on_value {
-                    if props.radio_group {
-                        // do not allow to deselect radio buttons (same behaviour as browser).
-                        on_value
-                    } else {
-                        String::new()
-                    }
+                let checked = state.value == props.submit_on_value;
+                let new_value = if checked {
+                    props.submit_off_value.clone()
                 } else {
-                    on_value
+                    props.submit_on_value.clone()
                 };
+                ctx.link().update_value(new_value);
 
-                let changes = value != new_value;
-
-                if changes {
-                    ctx.link().update_value(new_value.clone());
-
-                    if let Some(on_input) = &props.on_input {
-                        on_input.emit(new_value);
-                    }
+                if let Some(on_input) = &props.on_input {
+                    on_input.emit(!checked);
                 }
-                true
+
+                false
             }
         }
     }
 
-    fn changed(&mut self, ctx: &ManagedFieldContext<Self>, _old_props: &Self::Properties) -> bool {
+    fn value_changed(&mut self, ctx: &ManagedFieldContext<Self>) {
         let props = ctx.props();
+        let state = ctx.state();
+        let checked = state.value == props.submit_on_value;
+        if let Some(on_change) = &props.on_change {
+            on_change.emit(checked);
+        }
+    }
 
+    fn changed(&mut self, ctx: &ManagedFieldContext<Self>, _old_props: &Self::Properties) -> bool {
+        let props = ctx.props();
         if let Some(checked) = props.checked {
-            let on_value = props.value.as_deref().unwrap_or("on").to_string();
-            let value = if checked { on_value } else { String::new() };
-            ctx.link().force_value(Some(value), None);
+            let value = if checked {
+                props.submit_on_value.clone()
+            } else {
+                props.submit_off_value.clone()
+            };
+            ctx.link().force_value(Some(value), None)
         }
-
         true
     }
 
     fn view(&self, ctx: &ManagedFieldContext<Self>) -> Html {
         let props = ctx.props();
-        let state = ctx.state();
-
+        let link = ctx.link();
         let disabled = props.input_props.disabled;
 
-        let on_value = props.value.as_deref().unwrap_or("on").to_string();
+        let state = ctx.state();
+
         let (value, valid) = (&state.value, &state.valid);
-        let checked = *value == on_value;
+        let checked = {
+            let this = &props;
+            *value == this.submit_on_value
+        };
 
-        let onclick = ctx.link().callback(|_| Msg::Toggle);
+        let onclick = link.callback(|_| Msg::Toggle);
         let onkeyup = Callback::from({
-            let link = ctx.link().clone();
+            let link = link.clone();
             move |event: KeyboardEvent| {
                 if event.key() == " " {
                     link.send_message(Msg::Toggle);
@@ -261,44 +288,50 @@ impl ManagedField for CheckboxField {
             }
         });
 
-        let (layout_class, inner) = match (props.switch, props.radio_group) {
-            (true, _) => (
-                "pwt-switch",
-                html! {<span class="pwt-switch-slider"><i class="fa fa-check"/></span>},
-            ),
-            (false, true) => {
-                // Note: icon is invisible, but necessary for correct baseline alignment
-                (
-                    "pwt-radio-button",
-                    html! {<span class="pwt-checkbox-icon"><i class="fa fa-check"/></span>},
-                )
-            }
-            (false, false) => (
-                "pwt-checkbox",
-                html! {<span class="pwt-checkbox-icon"><i class="fa fa-check"/></span>},
-            ),
+        let (layout_class, inner_class) = match props.switch {
+            true => ("pwt-switch", "pwt-switch-slider"),
+            false => ("pwt-checkbox", "pwt-checkbox-icon"),
         };
 
+        let checkbox = Container::new()
+            .class((!props.switch).then_some("pwt-checkbox-state"))
+            .with_child(
+                Container::new()
+                    .class(layout_class)
+                    .with_child(
+                        Container::from_tag("span")
+                            .class(inner_class)
+                            .with_child(Fa::new("check")),
+                    )
+                    .class(checked.then_some("checked"))
+                    .class(disabled.then_some("disabled"))
+                    .class(if valid.is_ok() {
+                        "is-valid"
+                    } else {
+                        "is-invalid"
+                    })
+                    .attribute(
+                        "tabindex",
+                        props.input_props.tabindex.unwrap_or(0).to_string(),
+                    )
+                    .attribute("role", "checkbox")
+                    .attribute("aria-checked", checked.then_some("true"))
+                    .onkeyup(onkeyup),
+            );
+
+        let box_label = props.box_label.clone().map(|label| label.padding_start(2));
+
+        let checkbox = Row::new()
+            .class(AlignItems::Center)
+            .with_child(checkbox)
+            .with_optional_child(box_label);
+
         // TODO: add other props.input_props
 
-        let mut checkbox = Tooltip::new(inner)
+        let mut checkbox = Tooltip::new(checkbox)
             .with_std_props(&props.std_props)
             .listeners(&props.listeners)
-            .class(layout_class)
-            .class(checked.then(|| "checked"))
-            .class(disabled.then(|| "disabled"))
-            .class(if valid.is_ok() {
-                "is-valid"
-            } else {
-                "is-invalid"
-            })
-            .attribute(
-                "tabindex",
-                props.input_props.tabindex.unwrap_or(0).to_string(),
-            )
-            .attribute("role", "checkbox")
-            .attribute("aria-checked", checked.then(|| "true"))
-            .onkeyup(onkeyup);
+            .onclick(onclick);
 
         if let Err(msg) = &valid {
             checkbox.set_tip(msg.clone())
@@ -308,15 +341,7 @@ impl ManagedField for CheckboxField {
             }
         }
 
-        if props.switch {
-            checkbox.onclick(onclick).into()
-        } else {
-            Container::new()
-                .class("pwt-checkbox-state")
-                .onclick(onclick)
-                .with_child(checkbox)
-                .into()
-        }
+        checkbox.into()
     }
 
     fn rendered(&mut self, ctx: &ManagedFieldContext<Self>, first_render: bool) {
index 857ba4e9ccfacf61fea8f5e5d0cc40debf68df17..6bfcf656ce2286842796647b204725cbb45ba4ba 100644 (file)
@@ -564,7 +564,7 @@ impl FormContextState {
         }
     }
 
-    /// Get the field value as bool (for Checkbox and Boolean fields).
+    /// Get the field value as bool (for Checkbox fields).
     ///
     /// Return false for non-existent fields, empty fields, or
     /// when the field value not bool.
index 40927a01ee37c7ae29165323c5358af3ec2e21e7..3b29db0c2834d69c1e3975e935f39309286eb41f 100644 (file)
@@ -6,9 +6,6 @@ pub use context::{
     FormContextState, FormContextWriteGuard,
 };
 
-mod boolean;
-pub use boolean::{Boolean, PwtBoolean};
-
 mod tristate_boolean;
 pub use tristate_boolean::{PwtTristateBoolean, Tristate, TristateBoolean};