mirror of
https://github.com/adoyle0/thaw.git
synced 2025-01-22 22:09:22 -05:00
feat: SpinButton adds rules prop
This commit is contained in:
parent
51b04d911b
commit
e1e5c02e54
3 changed files with 64 additions and 3 deletions
|
@ -50,6 +50,17 @@ view! {
|
||||||
<ComboboxOption value="dog" text="Dog" />
|
<ComboboxOption value="dog" text="Dog" />
|
||||||
</Combobox>
|
</Combobox>
|
||||||
</Field>
|
</Field>
|
||||||
|
<Field name="spinbutton">
|
||||||
|
<SpinButton
|
||||||
|
step_page=1
|
||||||
|
rules=vec![SpinButtonRule::validator(move |v, _| {
|
||||||
|
if v % 2 == 0 {
|
||||||
|
Err(FieldValidationState::Error("It has to be odd!".to_string()))
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
})]/>
|
||||||
|
</Field>
|
||||||
<div style="margin-top: 8px">
|
<div style="margin-top: 8px">
|
||||||
<Button
|
<Button
|
||||||
button_type=ButtonType::Submit
|
button_type=ButtonType::Submit
|
||||||
|
|
|
@ -81,6 +81,9 @@ view! {
|
||||||
| Name | Type | Default | Description |
|
| Name | Type | Default | Description |
|
||||||
| --- | --- | --- | --- |
|
| --- | --- | --- | --- |
|
||||||
| class | `MaybeProp<String>` | `Default::default()` | |
|
| class | `MaybeProp<String>` | `Default::default()` | |
|
||||||
|
| id | `MaybeProp<String>` | `Default::default()` | |
|
||||||
|
| name | `MaybeProp<String>` | `Default::default()` | A string specifying a name for the input control. This name is submitted along with the control's value when the form data is submitted. |
|
||||||
|
| rules | `Vec<SpinButtonRule<T>>` | `vec![]` | The rules to validate Field. |
|
||||||
| value | `Model<T>` | `T::default()` | Current value of the control. |
|
| value | `Model<T>` | `T::default()` | Current value of the control. |
|
||||||
| placeholder | `MaybeProp<String>` | `Default::default()` | Placeholder of input number. |
|
| placeholder | `MaybeProp<String>` | `Default::default()` | Placeholder of input number. |
|
||||||
| step_page | `MaybeSignal<T>` | | Large difference between two values. This should be greater than step and is used when users hit the Page Up or Page Down keys. |
|
| step_page | `MaybeSignal<T>` | | Large difference between two values. This should be greater than step and is used when users hit the Page Up or Page Down keys. |
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
|
use crate::{FieldInjection, FieldValidationState, Rule};
|
||||||
use leptos::prelude::*;
|
use leptos::prelude::*;
|
||||||
use num_traits::Bounded;
|
use num_traits::Bounded;
|
||||||
use std::ops::{Add, Sub};
|
use std::ops::{Add, Deref, Sub};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use thaw_utils::{
|
use thaw_utils::{
|
||||||
class_list, mount_style, with, BoxOneCallback, Model, OptionalProp, StoredMaybeSignal,
|
class_list, mount_style, with, BoxOneCallback, Model, OptionalProp, StoredMaybeSignal,
|
||||||
|
@ -9,6 +10,13 @@ use thaw_utils::{
|
||||||
#[component]
|
#[component]
|
||||||
pub fn SpinButton<T>(
|
pub fn SpinButton<T>(
|
||||||
#[prop(optional, into)] class: MaybeProp<String>,
|
#[prop(optional, into)] class: MaybeProp<String>,
|
||||||
|
#[prop(optional, into)] id: MaybeProp<String>,
|
||||||
|
/// A string specifying a name for the input control.
|
||||||
|
/// This name is submitted along with the control's value when the form data is submitted.
|
||||||
|
#[prop(optional, into)]
|
||||||
|
name: MaybeProp<String>,
|
||||||
|
/// The rules to validate Field.
|
||||||
|
#[prop(optional, into)] rules: Vec<SpinButtonRule<T>>,
|
||||||
/// Current value of the control.
|
/// Current value of the control.
|
||||||
#[prop(optional, into)]
|
#[prop(optional, into)]
|
||||||
value: Model<T>,
|
value: Model<T>,
|
||||||
|
@ -41,22 +49,28 @@ where
|
||||||
T: Default + Clone + FromStr + ToString + 'static,
|
T: Default + Clone + FromStr + ToString + 'static,
|
||||||
{
|
{
|
||||||
mount_style("spin-button", include_str!("./spin-button.css"));
|
mount_style("spin-button", include_str!("./spin-button.css"));
|
||||||
|
let (id, name) = FieldInjection::use_id_and_name(id, name);
|
||||||
|
let validate = Rule::validate(rules, value, name);
|
||||||
let initialization_value = value.get_untracked().to_string();
|
let initialization_value = value.get_untracked().to_string();
|
||||||
let step_page: StoredMaybeSignal<_> = step_page.into();
|
let step_page: StoredMaybeSignal<_> = step_page.into();
|
||||||
let min: StoredMaybeSignal<_> = min.into();
|
let min: StoredMaybeSignal<_> = min.into();
|
||||||
let max: StoredMaybeSignal<_> = max.into();
|
let max: StoredMaybeSignal<_> = max.into();
|
||||||
|
|
||||||
let update_value = move |new_value| {
|
let update_value = move |new_value| {
|
||||||
|
if with!(|value| value == &new_value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
let min = min.get_untracked();
|
let min = min.get_untracked();
|
||||||
let max = max.get_untracked();
|
let max = max.get_untracked();
|
||||||
|
|
||||||
if new_value < min {
|
if new_value < min {
|
||||||
value.set(min);
|
value.set(min);
|
||||||
} else if new_value > max {
|
} else if new_value > max {
|
||||||
value.set(max);
|
value.set(max);
|
||||||
} else if with!(|value| value != &new_value) {
|
} else {
|
||||||
value.set(new_value);
|
value.set(new_value);
|
||||||
}
|
}
|
||||||
|
validate.run(Some(SpinButtonRuleTrigger::Change));
|
||||||
};
|
};
|
||||||
|
|
||||||
let increment_disabled = Memo::new(move |_| disabled.get() || value.get() >= max.get());
|
let increment_disabled = Memo::new(move |_| disabled.get() || value.get() >= max.get());
|
||||||
|
@ -100,6 +114,8 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
class="thaw-spin-button__input"
|
class="thaw-spin-button__input"
|
||||||
|
id=id
|
||||||
|
name=name
|
||||||
on:change=on_change
|
on:change=on_change
|
||||||
/>
|
/>
|
||||||
<button
|
<button
|
||||||
|
@ -163,3 +179,34 @@ where
|
||||||
</span>
|
</span>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default, PartialEq, Clone, Copy)]
|
||||||
|
pub enum SpinButtonRuleTrigger {
|
||||||
|
#[default]
|
||||||
|
Change,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct SpinButtonRule<T>(Rule<T, SpinButtonRuleTrigger>);
|
||||||
|
|
||||||
|
impl<T> SpinButtonRule<T> {
|
||||||
|
pub fn validator(
|
||||||
|
f: impl Fn(&T, Signal<Option<String>>) -> Result<(), FieldValidationState>
|
||||||
|
+ Send
|
||||||
|
+ Sync
|
||||||
|
+ 'static,
|
||||||
|
) -> Self {
|
||||||
|
Self(Rule::validator(f))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_trigger(self, trigger: SpinButtonRuleTrigger) -> Self {
|
||||||
|
Self(Rule::with_trigger(self.0, trigger))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Deref for SpinButtonRule<T> {
|
||||||
|
type Target = Rule<T, SpinButtonRuleTrigger>;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue