Skip to main content

patternfly_yew/components/form/
validation.rs

1use crate::prelude::{AsClasses, FormHelperText, Icon, ValidationContext};
2use yew::{Callback, Classes};
3
4/// State of an input from validation
5#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, PartialOrd, Ord)]
6pub enum InputState {
7    #[default]
8    Default,
9    Success,
10    Warning,
11    Error,
12}
13
14impl AsClasses for InputState {
15    fn extend_classes(&self, classes: &mut Classes) {
16        match self {
17            Self::Default => {}
18            Self::Success => classes.push("pf-m-success"),
19            Self::Warning => classes.push("pf-m-warning"),
20            Self::Error => classes.push("pf-m-error"),
21        }
22    }
23}
24
25impl InputState {
26    pub fn convert(&self, mut classes: Classes) -> (Classes, bool) {
27        let mut aria_invalid = false;
28        match self {
29            InputState::Default => {}
30            InputState::Success => classes.push("pf-m-success"),
31            InputState::Warning => classes.push("pf-m-warning"),
32            InputState::Error => {
33                classes.push("pf-m-error");
34                aria_invalid = true;
35            }
36        };
37        (classes, aria_invalid)
38    }
39
40    pub fn icon(&self) -> Icon {
41        match self {
42            Self::Default => Icon::Minus,
43            Self::Success => Icon::CheckCircle,
44            Self::Warning => Icon::ExclamationTriangle,
45            Self::Error => Icon::ExclamationCircle,
46        }
47    }
48}
49
50/// Result of the validation
51#[derive(Clone, Debug, PartialEq, Eq)]
52pub struct ValidationResult {
53    pub message: Option<String>,
54    pub state: InputState,
55}
56
57impl From<ValidationResult> for Option<FormHelperText> {
58    fn from(result: ValidationResult) -> Self {
59        if matches!(result.state, InputState::Default) || result.message.is_none() {
60            // default state and no message
61            None
62        } else {
63            // non-default state or some message
64            Some(FormHelperText {
65                message: result.message.unwrap_or_default(),
66                input_state: result.state,
67                custom_icon: None,
68                no_icon: matches!(result.state, InputState::Default),
69                is_dynamic: true,
70            })
71        }
72    }
73}
74
75impl Default for ValidationResult {
76    fn default() -> Self {
77        ValidationResult::ok()
78    }
79}
80
81impl ValidationResult {
82    pub fn ok() -> Self {
83        Self {
84            message: None,
85            state: Default::default(),
86        }
87    }
88
89    pub fn new<S: Into<String>>(state: InputState, message: S) -> Self {
90        Self {
91            state,
92            message: Some(message.into()),
93        }
94    }
95
96    pub fn help<S: Into<String>>(message: S) -> Self {
97        Self::new(InputState::Default, message)
98    }
99
100    pub fn error<S: Into<String>>(message: S) -> Self {
101        Self::new(InputState::Error, message)
102    }
103
104    pub fn warning<S: Into<String>>(message: S) -> Self {
105        Self::new(InputState::Warning, message)
106    }
107}
108
109/// A component supporting validation.
110pub trait ValidatingComponent {
111    type Value;
112}
113
114/// A trait which components supporting validatio must implement.
115pub trait ValidatingComponentProperties<T> {
116    fn set_onvalidate(&mut self, onvalidate: Callback<ValidationContext<T>>);
117    fn set_input_state(&mut self, state: InputState);
118}