AsyncField
import 'package:fform/fform.dart';
/// Custom error type for the email field
enum EmailError {
empty, // The email field is empty
invalidFormat, // The email does not contain a valid format
alreadyTaken // The email is already taken (validated asynchronously)
}
/// A form field for validating email addresses
class EmailField extends FFormField<String, EmailError> with AsyncField<String, EmailError> {
/// Initializes the email field with an initial value.
EmailField({required String value}) : super(value);
/// Synchronous validation for basic checks.
EmailError? validator(String value) {
if (value.isEmpty) {
return EmailError.empty; // Email field cannot be empty
}
if (!RegExp(r'^[^@]+@[^@]+\.[^@]+').hasMatch(value)) {
return EmailError.invalidFormat; // Email must match the basic email pattern
}
return null; // The email passes synchronous validation
}
/// Asynchronous validation for additional checks, such as server-side verification.
Future<EmailError?> asyncValidator(String value) async {
await Future.delayed(Duration(seconds: 1)); // Simulate a network delay
const existingEmails = ['test@example.com', 'user@domain.com'];
if (existingEmails.contains(value)) {
return EmailError.alreadyTaken; // Email is already registered
}
return null; // The email passes asynchronous validation
}
}
Explanation of the Example​
1. Purpose of the EmailField
Class​
The EmailField
class represents a form field specifically designed to validate email addresses. It combines:
- Synchronous validation (
validator
): Basic checks like ensuring the email is not empty and has a valid format. - Asynchronous validation (
asyncValidator
): More complex checks, such as verifying if the email is already registered, which typically requires communication with a server.
2. Synchronous Validation (validator
)​
The validator
method is designed for lightweight, immediate checks:
value.isEmpty
: Ensures the email is not empty.- Regex validation: Checks if the email matches a basic pattern for valid email addresses.
If the value passes these checks, null
is returned, indicating no errors.
3. Asynchronous Validation (asyncValidator
)​
The asyncValidator
method is where you can perform time-consuming checks, such as querying a database or an API:
- A simulated network delay of 1 second is added using
Future.delayed
. - A list of
existingEmails
is used to check if the entered email is already registered.
If the email is found in the list, EmailError.alreadyTaken
is returned; otherwise, it passes validation.
Advantages of the AsyncField
Mixin​
The AsyncField
mixin allows you to separate immediate validation from time-consuming checks. This approach has several benefits:
-
Improved User Experience:
- Basic validation errors are shown instantly.
- Advanced checks (like server-side validation) occur in the background, avoiding delays in user feedback.
-
Modular Design:
- Validation logic is clearly divided between
validator
andasyncValidator
, making it easier to manage and test.
- Validation logic is clearly divided between
-
Compatibility with Form Frameworks:
- Supports scenarios where fields need to be validated asynchronously before allowing the form submission.
Suggested Improvements for Your Application​
- Use localized error messages: Map
EmailError
enum values to user-friendly error strings. - Customize validation delays: Replace the
Future.delayed
with actual server calls or a mock service for testing. - Dynamic constraints: Allow the
existingEmails
list to be passed as a parameter to make the field reusable in multiple contexts. - Use checkAsync Method in Form:
fform.checkAsync()