diff --git a/nicegui/elements/input.py b/nicegui/elements/input.py index 4077dedda..3429b3f60 100644 --- a/nicegui/elements/input.py +++ b/nicegui/elements/input.py @@ -46,7 +46,7 @@ def __init__(self, :param password_toggle_button: whether to show a button to toggle the password visibility (default: False) :param on_change: callback to execute when the value changes :param autocomplete: optional list of strings for autocompletion - :param validation: dictionary of validation rules or a callable that returns an optional error message + :param validation: dictionary of validation rules or a callable that returns an optional error message (default: None for no validation) """ super().__init__(value=value, on_value_change=on_change, validation=validation) if label is not None: diff --git a/nicegui/elements/mixins/validation_element.py b/nicegui/elements/mixins/validation_element.py index 6a284addc..1f0e5ca1d 100644 --- a/nicegui/elements/mixins/validation_element.py +++ b/nicegui/elements/mixins/validation_element.py @@ -8,11 +8,25 @@ class ValidationElement(ValueElement): def __init__(self, validation: Optional[Union[Callable[..., Optional[str]], Dict[str, Callable[..., bool]]]], **kwargs: Any) -> None: - self.validation = validation if validation is not None else {} + self._validation = validation self._auto_validation = True self._error: Optional[str] = None super().__init__(**kwargs) - self._props['error'] = False # NOTE: reserve bottom space for error message + self._props['error'] = None if validation is None else False # NOTE: reserve bottom space for error message + + @property + def validation(self) -> Optional[Union[Callable[..., Optional[str]], Dict[str, Callable[..., bool]]]]: + """The validation function or dictionary of validation functions.""" + return self._validation + + @validation.setter + def validation(self, validation: Optional[Union[Callable[..., Optional[str]], Dict[str, Callable[..., bool]]]]) -> None: + """Sets the validation function or dictionary of validation functions. + + :param validation: validation function or dictionary of validation functions (``None`` to disable validation) + """ + self._validation = validation + self.validate() @property def error(self) -> Optional[str]: @@ -25,10 +39,11 @@ def error(self, error: Optional[str]) -> None: :param error: The optional error message """ - if self._error == error: + new_error_prop = None if self.validation is None else (error is not None) + if self._error == error and self._props['error'] == new_error_prop: return self._error = error - self._props['error'] = error is not None + self._props['error'] = new_error_prop self._props['error-message'] = error self.update() @@ -37,14 +52,15 @@ def validate(self) -> bool: :return: True if the value is valid, False otherwise """ - if callable(self.validation): - self.error = self.validation(self.value) + if callable(self._validation): + self.error = self._validation(self.value) return self.error is None - for message, check in self.validation.items(): - if not check(self.value): - self.error = message - return False + if isinstance(self._validation, dict): + for message, check in self._validation.items(): + if not check(self.value): + self.error = message + return False self.error = None return True diff --git a/nicegui/elements/number.py b/nicegui/elements/number.py index ae45487a0..6e6dc19c8 100644 --- a/nicegui/elements/number.py +++ b/nicegui/elements/number.py @@ -43,7 +43,7 @@ def __init__(self, :param suffix: a suffix to append to the displayed value :param format: a string like "%.2f" to format the displayed value :param on_change: callback to execute when the value changes - :param validation: dictionary of validation rules or a callable that returns an optional error message + :param validation: dictionary of validation rules or a callable that returns an optional error message (default: None for no validation) """ self.format = format super().__init__(tag='q-input', value=value, on_value_change=on_change, validation=validation) diff --git a/nicegui/elements/select.py b/nicegui/elements/select.py index 9eec48f3a..469f8b386 100644 --- a/nicegui/elements/select.py +++ b/nicegui/elements/select.py @@ -49,7 +49,7 @@ def __init__(self, :param new_value_mode: handle new values from user input (default: None, i.e. no new values) :param multiple: whether to allow multiple selections :param clearable: whether to add a button to clear the selection - :param validation: dictionary of validation rules or a callable that returns an optional error message + :param validation: dictionary of validation rules or a callable that returns an optional error message (default: None for no validation) :param key_generator: a callback or iterator to generate a dictionary key for new values """ self.multiple = multiple diff --git a/nicegui/elements/textarea.py b/nicegui/elements/textarea.py index c29a5cac6..2aa03ec38 100644 --- a/nicegui/elements/textarea.py +++ b/nicegui/elements/textarea.py @@ -27,7 +27,7 @@ def __init__(self, :param placeholder: text to show if no value is entered :param value: the initial value of the field :param on_change: callback to execute when the value changes - :param validation: dictionary of validation rules or a callable that returns an optional error message + :param validation: dictionary of validation rules or a callable that returns an optional error message (default: None for no validation) """ super().__init__(label, placeholder=placeholder, value=value, on_change=on_change, validation=validation) self._props['type'] = 'textarea'