formz

repository·main·Indexed 19 days ago

https://github.com/verygoodopensource/formz

A unified form representation library for Dart that simplifies form management and validation. It provides the FormzInput class for individual inputs, FormzMixin for unified form objects, and FormzInputErrorCacheMixin to cache expensive validation results.

Tokens
1.7K
Snippets
6
Records
6
Agent score
17%

What's inside formz

  1. How automatic validation works with FormzMixin

    main

    You can create a unified form object (like a LoginForm) by using the FormzMixin. By implementing the inputs getter to return a list of your FormzInput objects, the mixin provides an isValid property for the entire form.

    1. Create a class representing your form.
    2. Mix in FormzMixin.
    3. Override List<FormzInput> get inputs to return all fields in the form.
    class LoginForm with FormzMixin {
      LoginForm({
        this.username = const Username.pure(),
        this.password = const Password.pure(),
      });
    
      final Username username;
      final Password password;
    
      @override
      List<FormzInput> get inputs => [username, password];
    }
    
    void main() {
      print(LoginForm().isValid); // false
    }
  2. Create a FormzInput

    main

    To represent a form field, extend the FormzInput<Value, Error> class. You must provide the type of the input value and the type of the validation error (usually an enum).

    Key concepts:

    • Pure state: Use FormzInput.pure() to represent an unmodified input (e.g., the initial state of a form).
    • Dirty state: Use FormzInput.dirty({Value value}) to represent an input that has been modified by a user.
    • Validator: Override the validator(Value value) method to return an error of your error type if the input is invalid, or null if it is valid.
    import 'package:formz/formz.dart';
    
    // Define input validation errors
    enum NameInputError { empty }
    
    // Extend FormzInput and provide the input type and error type.
    class NameInput extends FormzInput<String, NameInputError> {
      // Call super.pure to represent an unmodified form input.
      const NameInput.pure() : super.pure('');
    
      // Call super.dirty to represent a modified form input.
      const NameInput.dirty({String value = ''}) : super.dirty(value);
    
      // Override validator to handle validating a given input value.
      @override
      NameInputError? validator(String value) {
        return value.isEmpty ? NameInputError.empty : null;
      }
    }
  3. Customize iOS Launch Screen Assets

    main

    To customize the iOS launch screen, you can replace the existing image files in the example/ios/Runner/Assets.xcassets/LaunchImage.imageset/ directory with your own assets.

    Alternatively, you can manage these assets through Xcode:

    1. Open the iOS workspace using: open ios/Runner.xcworkspace.
    2. In the Xcode Project Navigator, navigate to Runner/Assets.xcassets.
    3. Drag and drop your desired images into the asset catalog.
    open ios/Runner.xcworkspace
  4. Interact with a FormzInput

    main

    Once a FormzInput is created, you can inspect its state using the following properties:

    • value: The current value of the input.
    • isValid: A boolean indicating if the input passed validation.
    • error: The specific error returned by the validator (returns null if valid).
    • displayError: A convenience property for showing errors (typically used in UI to show errors only when the input is 'dirty').
    const name = NameInput.pure();
    print(name.value); // ''
    print(name.isValid); // false
    print(name.error); // NameInputError.empty
    print(name.displayError); // null
    
    const joe = NameInput.dirty(value: 'joe');
    print(joe.value); // 'joe'
    print(joe.isValid); // true
    print(joe.error); // null
    print(joe.displayError); // null
  5. Cache validation results with FormzInputErrorCacheMixin

    main

    If your validator implementation is computationally expensive (e.g., complex Regex or heavy logic), use the FormzInputErrorCacheMixin. This mixin caches the result of the error property to improve performance by avoiding redundant validation calls.

    import 'package:formz/formz.dart';
    
    enum EmailValidationError { invalid }
    
    class Email extends FormzInput<String, EmailValidationError>
        with FormzInputErrorCacheMixin {
      Email.pure([super.value = '']) : super.pure();
    
      Email.dirty([super.value = '']) : super.dirty();
    
      static final _emailRegExp = RegExp(
        r'^[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$',
      );
    
      @override
      EmailValidationError? validator(String value) {
        return _emailRegExp.hasMatch(value) ? null : EmailValidationError.invalid;
      }
    }
  6. Validate Multiple FormzInput Items

    main

    To validate an entire form consisting of multiple inputs, use the Formz.validate() method. Pass a list of FormzInput objects to this method; it returns true only if all inputs in the list are valid.

    const validInputs = <FormzInput>[
      NameInput.dirty(value: 'jan'),
      NameInput.dirty(value: 'jen'),
      NameInput.dirty(value: 'joe'),
    ];
    
    print(Formz.validate(validInputs)); // true
    
    const invalidInputs = <FormzInput>[
      NameInput.dirty(),
      NameInput.dirty(),
      NameInput.dirty(),
    ];
    
    print(Formz.validate(invalidInputs)); // false