Add validate feature

This commit is contained in:
Thomas Gideon 2021-04-11 11:29:42 -04:00
parent 2541c89161
commit bff36b0ce3
3 changed files with 69 additions and 6 deletions

View file

@ -7,6 +7,9 @@ edition = "2018"
[lib]
crate-type = ["cdylib", "rlib"]
[features]
validate = [ "validator" ]
[dependencies]
yew = "~0.17.2"
log = "~0.4.8"
@ -18,3 +21,4 @@ web-sys = "~0.3.38"
wasm-logger = "~0.2.0"
yew-router = "~0.14.0"
yew-components = "~0.2.0"
validator = { optional = true, version = "~0.13.0" }

View file

@ -6,6 +6,8 @@ use self::props::Props;
pub use self::{group::InputGroup, textarea::TextArea};
use crate::{prelude::*, render};
use std::fmt::{Display, Formatter, Result as FmtResult};
#[cfg(feature = "validate")]
use validator::ValidationErrors;
use yew::prelude::*;
#[derive(Clone, PartialEq)]
@ -65,11 +67,7 @@ impl Component for Input {
}
fn view(&self) -> Html {
let input_type = self
.props
.input_type
.as_ref()
.unwrap_or_else(|| &InputType::Text);
let input_type = self.props.input_type.as_ref().unwrap_or(&InputType::Text);
let mut prefix = if self.props.readonly {
vec!["form-control-plaintext"]
} else {
@ -87,3 +85,21 @@ impl Component for Input {
render::render_with_prefix(&self.props, prefix, html)
}
}
#[cfg(feature = "validate")]
fn render_validation_feedback<S: AsRef<str>>(field: S, errors: &Option<ValidationErrors>) -> Html {
if let Some(ref errors) = errors {
let errors = errors.field_errors();
if let Some(errors) = errors.get(field.as_ref()) {
html! {
<div class="invalid-feedback">
{ for errors.iter().filter_map(|error| error.message.as_ref()) }
</div>
}
} else {
html! {}
}
} else {
html! {}
}
}

View file

@ -1,11 +1,15 @@
use super::props::Props;
use crate::{prelude::*, render};
#[cfg(feature = "validate")]
use validator::ValidationErrors;
use yew::{prelude::*, virtual_dom::VNode};
pub struct TextArea {
link: ComponentLink<Self>,
state: String,
props: Props,
#[cfg(feature = "validator")]
errors: Option<ValidationErrors>,
}
#[derive(Debug)]
@ -15,11 +19,23 @@ impl Component for TextArea {
type Message = InputChange;
type Properties = Props;
#[cfg(not(feature = "validate"))]
fn create(props: Self::Properties, link: ComponentLink<Self>) -> Self {
let state = extract_state(&props);
Self { props, state, link }
}
#[cfg(feature = "validate")]
fn create(props: Self::Properties, link: ComponentLink<Self>) -> Self {
let state = extract_state(&props);
Self {
props,
state,
link,
errors: None,
}
}
fn update(&mut self, msg: Self::Message) -> ShouldRender {
if let InputChange(ChangeData::Value(value)) = msg {
self.state = value.clone();
@ -38,15 +54,42 @@ impl Component for TextArea {
should_render
}
#[cfg(not(feature = "validate"))]
fn view(&self) -> Html {
let prefix = vec!["form-control", &valid_as_class(&self.props.valid)];
let html = html! {
let html = {
html! {
<textarea
readonly=self.props.readonly
onchange=self.link.callback(|evt| InputChange(evt))
>
{ &self.state }
</textarea>
}
};
render::render_with_prefix(&self.props, prefix, html)
}
#[cfg(feature = "validate")]
fn view(&self) -> Html {
let prefix = vec!["form-control", &valid_as_class(&self.props.valid)];
let feedback = if let Some(name) = self.props.name.as_ref() {
super::render_validation_feedback(name, &self.errors)
} else {
html! {}
};
let html = {
html! {
<>
{ feedback }
<textarea
readonly=self.props.readonly
onchange=self.link.callback(|evt| InputChange(evt))
>
{ &self.state }
</textarea>
</>
}
};
render::render_with_prefix(&self.props, prefix, html)
}