Skip to main content

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:

  1. Improved User Experience:

    • Basic validation errors are shown instantly.
    • Advanced checks (like server-side validation) occur in the background, avoiding delays in user feedback.
  2. Modular Design:

    • Validation logic is clearly divided between validator and asyncValidator, making it easier to manage and test.
  3. Compatibility with Form Frameworks:

    • Supports scenarios where fields need to be validated asynchronously before allowing the form submission.

Suggested Improvements for Your Application​

  1. Use localized error messages: Map EmailError enum values to user-friendly error strings.
  2. Customize validation delays: Replace the Future.delayed with actual server calls or a mock service for testing.
  3. Dynamic constraints: Allow the existingEmails list to be passed as a parameter to make the field reusable in multiple contexts.
  4. Use checkAsync Method in Form: fform.checkAsync()