Validation with external information
ayalma opened this issue Β· comments
Hi and thank you for lib
How to validate input with external information like checking username availability , or checking password confirmation?
Thank you for your response.
For password confirmation we can use this way
But for sth like checking username availability with server , or loading dropdown items from server
I think we must be able to show loading indicator or error in ui with aid of input
@felangel, I'm also curious about how to implement server-side validation using Formz (e.g. email uniqueness check). Could there be some way of manually setting errors on FormzInput instances?
Love to hear your thoughts, and I'm happy to PR such functionality.
This is how I ended up doing it. I feels, however, that there should be a better way built into the library:
enum PasswordValidationError { empty, authFailed }
class Password extends FormzInput<String, PasswordValidationError> {
const Password.pure({this.externalError}) : super.pure('');
const Password.dirty({
this.externalError,
String value = '',
}) : super.dirty(value);
final PasswordValidationError externalError;
@override
PasswordValidationError validator(String value) {
if (externalError != null) {
return externalError;
} else if (value?.isNotEmpty == false) {
return PasswordValidationError.empty;
}
return null;
}
}
@djensen47, thanks for your workaround. I'd also been thinking about it, but it just doesn't feel right.
I've talked to @felangel, and he'll take a look soon.
Thanks for everyone's patience! I am actively discussing ways to achieve this and will report back with a proposal shortly π
@felangel, have you been able to come up with a proposal?
A more abstract version of @djensen47's approach would be:
-
Create
extended_formz_input.dart
:import 'package:formz/formz.dart'; abstract class ExtendedFormzInput<T, E> extends FormzInput<T, E> { final E externalError; const ExtendedFormzInput.pure(T value) : externalError = null, super.pure(value); const ExtendedFormzInput.dirty(T value, this.externalError) : super.dirty(value); ExtendedFormzInput copyWithExternalError(E error); @override E get error => externalError ?? super.error; @override bool get valid => error == null; @override int get hashCode => value.hashCode ^ pure.hashCode ^ externalError.hashCode; @override bool operator ==(Object other) { if (other.runtimeType != runtimeType) return false; return other is ExtendedFormzInput<T, E> && other.value == value && other.externalError == externalError && other.pure == pure; } }
-
Extend it instead of
FormzInput
:import 'extended_formz_input.dart'; enum EmailInputError { empty, used } class EmailInput extends ExtendedFormzInput<String, EmailInputError> { const EmailInput.pure() : super.pure(''); const EmailInput.dirty(String value, [EmailInputError externalError]) : super.dirty(value, externalError); @override EmailInputError validator(String value) { return value?.isNotEmpty == true ? null : EmailInputError.empty; } @override EmailInput copyWithExternalError(EmailInputError error) { return EmailInput.dirty(value, error); } }
-
Use it:
final emailInput = EmailInput.dirty(email); // Do some external validation final newEmailInput = emailInput.copyWithExternalError(EmailInputError.used);
Closing for now but feel free to comment with any additional questions and I'm happy to continue the conversation π