mirror of
https://github.com/adoyle0/thaw.git
synced 2025-01-23 06:19:22 -05:00
fix: Input validate
This commit is contained in:
parent
615c33a5c8
commit
c0bd42ad60
5 changed files with 59 additions and 18 deletions
|
@ -27,8 +27,11 @@ view! {
|
||||||
view! {
|
view! {
|
||||||
<form>
|
<form>
|
||||||
<FieldContextProvider>
|
<FieldContextProvider>
|
||||||
<Field label="Example field">
|
<Field label="Username" name="username">
|
||||||
<Input />
|
<Input rules=vec![InputRule::required(true.into())]/>
|
||||||
|
</Field>
|
||||||
|
<Field label="Password" name="password">
|
||||||
|
<Input input_type=InputType::Password rules=vec![InputRule::required(true.into())]/>
|
||||||
</Field>
|
</Field>
|
||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
|
|
|
@ -37,6 +37,10 @@
|
||||||
line-height: var(--lineHeightBase200);
|
line-height: var(--lineHeightBase200);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.thaw-field--error > .thaw-field__validation-message {
|
||||||
|
color: var(--colorPaletteRedForeground1);
|
||||||
|
}
|
||||||
|
|
||||||
.thaw-field__validation-message-icon {
|
.thaw-field__validation-message-icon {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
|
|
|
@ -25,6 +25,15 @@ pub fn Field(
|
||||||
move || {
|
move || {
|
||||||
format!("thaw-field--{}", orientation.get().as_str())
|
format!("thaw-field--{}", orientation.get().as_str())
|
||||||
},
|
},
|
||||||
|
move || {
|
||||||
|
validation_state.with(|state| {
|
||||||
|
if let Some(state) = state {
|
||||||
|
Some(format!("thaw-field--{}", state.as_str()))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
class
|
class
|
||||||
]>
|
]>
|
||||||
{
|
{
|
||||||
|
@ -201,3 +210,13 @@ pub enum FieldValidationState {
|
||||||
Success(String),
|
Success(String),
|
||||||
Warning(String),
|
Warning(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl FieldValidationState {
|
||||||
|
pub fn as_str(&self) -> &'static str {
|
||||||
|
match self {
|
||||||
|
Self::Error(_) => "error",
|
||||||
|
Self::Success(_) => "success",
|
||||||
|
Self::Warning(_) => "warning",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -26,10 +26,17 @@ impl FieldContextInjection {
|
||||||
use_context()
|
use_context()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn register_field(&self, name: Signal<Option<String>>, validate: impl Fn() -> bool + Send + Sync + 'static) {
|
pub(crate) fn register_field(
|
||||||
|
&self,
|
||||||
|
name: Signal<Option<String>>,
|
||||||
|
validate: impl Fn() -> bool + Send + Sync + 'static,
|
||||||
|
) {
|
||||||
let mut key = None;
|
let mut key = None;
|
||||||
self.0
|
let validate = Callback::from(move |_| validate());
|
||||||
.update_value(|map| key = Some(map.insert((name, Callback::from(move |_| validate())))));
|
self.0.update_value(|map| {
|
||||||
|
key = Some(map.insert((name, validate)));
|
||||||
|
()
|
||||||
|
});
|
||||||
|
|
||||||
let map = self.0.clone();
|
let map = self.0.clone();
|
||||||
Owner::on_cleanup(move || {
|
Owner::on_cleanup(move || {
|
||||||
|
@ -39,12 +46,13 @@ impl FieldContextInjection {
|
||||||
|
|
||||||
pub fn validate(&self) -> bool {
|
pub fn validate(&self) -> bool {
|
||||||
self.0.with_value(|map| {
|
self.0.with_value(|map| {
|
||||||
|
let mut rt = true;
|
||||||
for (_, (_, validate)) in map.iter() {
|
for (_, (_, validate)) in map.iter() {
|
||||||
if !validate.run(()) {
|
if !validate.run(()) {
|
||||||
return false;
|
rt = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
true
|
rt
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -75,13 +75,13 @@ pub fn Input(
|
||||||
return None;
|
return None;
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Err(state) = rule.call_validator(trigger, value) {
|
if let Err(state) = rule.call_validator(trigger, value, name) {
|
||||||
return Some(state);
|
return Some(state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let rt = state.is_some();
|
let rt = state.is_none();
|
||||||
if let Some(field_injection) = field_injection.as_ref() {
|
if let Some(field_injection) = field_injection.as_ref() {
|
||||||
field_injection.update_validation_state(state);
|
field_injection.update_validation_state(state);
|
||||||
};
|
};
|
||||||
|
@ -318,7 +318,9 @@ impl InputRule {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn validator(f: impl Fn(&String) -> Result<(), FieldValidationState> + Send + Sync + 'static) -> Self {
|
pub fn validator(
|
||||||
|
f: impl Fn(&String) -> Result<(), FieldValidationState> + Send + Sync + 'static,
|
||||||
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
trigger: Default::default(),
|
trigger: Default::default(),
|
||||||
validator: InputRuleValidator::Validator(Callback::from(move |v| f(&v))),
|
validator: InputRuleValidator::Validator(Callback::from(move |v| f(&v))),
|
||||||
|
@ -335,6 +337,7 @@ impl InputRule {
|
||||||
&self,
|
&self,
|
||||||
trigger: Option<InputRuleTrigger>,
|
trigger: Option<InputRuleTrigger>,
|
||||||
value: Model<String>,
|
value: Model<String>,
|
||||||
|
name: Signal<Option<String>>,
|
||||||
) -> Result<(), FieldValidationState> {
|
) -> Result<(), FieldValidationState> {
|
||||||
if let Some(trigger) = trigger {
|
if let Some(trigger) = trigger {
|
||||||
if self.trigger != trigger {
|
if self.trigger != trigger {
|
||||||
|
@ -345,7 +348,11 @@ impl InputRule {
|
||||||
value.with_untracked(|value| match &self.validator {
|
value.with_untracked(|value| match &self.validator {
|
||||||
InputRuleValidator::Required(required) => {
|
InputRuleValidator::Required(required) => {
|
||||||
if required.get_untracked() && value.is_empty() {
|
if required.get_untracked() && value.is_empty() {
|
||||||
Err(FieldValidationState::Error(String::from("")))
|
let message = name.get_untracked().map_or_else(
|
||||||
|
|| String::from("Please input!"),
|
||||||
|
|name| format!("Please input {name}!"),
|
||||||
|
);
|
||||||
|
Err(FieldValidationState::Error(message))
|
||||||
} else {
|
} else {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue